@mui/x-virtualizer 0.2.8 → 0.2.10
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 +175 -0
- package/esm/features/dimensions.d.ts +3 -2
- package/esm/features/dimensions.js +7 -15
- package/esm/features/virtualization.d.ts +5 -5
- package/esm/features/virtualization.js +88 -27
- package/esm/index.js +1 -1
- package/esm/useVirtualizer.d.ts +6 -7
- package/features/dimensions.d.ts +3 -2
- package/features/dimensions.js +7 -14
- package/features/virtualization.d.ts +5 -5
- package/features/virtualization.js +87 -26
- package/index.js +1 -1
- package/package.json +2 -2
- package/useVirtualizer.d.ts +6 -7
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,181 @@
|
|
|
5
5
|
All notable changes to this project will be documented in this file.
|
|
6
6
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
7
7
|
|
|
8
|
+
## 8.20.0
|
|
9
|
+
|
|
10
|
+
_Nov 26, 2025_
|
|
11
|
+
|
|
12
|
+
We'd like to extend a big thank you to the 8 contributors who made this release possible. Here are some highlights ✨:
|
|
13
|
+
|
|
14
|
+
- 🔃 Data Grid tree data now supports row reordering. See the [Drag-and-drop tree data reordering](https://mui.com/x/react-data-grid/tree-data/#drag-and-drop-tree-data-reordering) section for more details.
|
|
15
|
+
- 🐞 Bugfixes
|
|
16
|
+
|
|
17
|
+
The following team members contributed to this release:
|
|
18
|
+
@alexfauquette, @arminmeh, @bernardobelchior, @cherniavskii, @siriwatknp, @JCQuintas, @MBilalShafi, @prakhargupta1
|
|
19
|
+
|
|
20
|
+
### Data Grid
|
|
21
|
+
|
|
22
|
+
#### `@mui/x-data-grid@8.20.0`
|
|
23
|
+
|
|
24
|
+
- [DataGrid] Fix RTL virtualization to display columns when viewport width is larger than the grid (#20409) @siriwatknp
|
|
25
|
+
- [DataGrid] Fix row range selection (#20442) @arminmeh
|
|
26
|
+
- [DataGrid] Initialize data grid core packages (#20276) @cherniavskii
|
|
27
|
+
- [DataGrid] Improve accessibility of the sort icon (#20430) @arminmeh
|
|
28
|
+
- [DataGrid] Use `viewport` as a boundary for the `BasePopper` flip (#20311) @arminmeh
|
|
29
|
+
|
|
30
|
+
#### `@mui/x-data-grid-pro@8.20.0` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
31
|
+
|
|
32
|
+
Same changes as in `@mui/x-data-grid@8.20.0`, plus:
|
|
33
|
+
|
|
34
|
+
- [DataGridPro] Avoid automatic scroll back to the focused header filter after it leaves the viewport (#20416) @arminmeh
|
|
35
|
+
- [DataGridPro] Tree data row reordering (#19401) @MBilalShafi
|
|
36
|
+
|
|
37
|
+
#### `@mui/x-data-grid-premium@8.20.0` [](https://mui.com/r/x-premium-svg-link 'Premium plan')
|
|
38
|
+
|
|
39
|
+
Same changes as in `@mui/x-data-grid-pro@8.20.0`.
|
|
40
|
+
|
|
41
|
+
### Charts
|
|
42
|
+
|
|
43
|
+
#### `@mui/x-charts@8.20.0`
|
|
44
|
+
|
|
45
|
+
- [charts] Fix item tooltip position with node anchor (#20421) @alexfauquette
|
|
46
|
+
- [charts] Fix radar item tooltip closing bug (#20429) @alexfauquette
|
|
47
|
+
- [charts] Move series processing to selector (#20388) @JCQuintas
|
|
48
|
+
- [charts] Prevent pointer out from removing controlled highlight (#20385) @alexfauquette
|
|
49
|
+
|
|
50
|
+
#### `@mui/x-charts-pro@8.20.0` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
51
|
+
|
|
52
|
+
Same changes as in `@mui/x-charts@8.20.0`, plus:
|
|
53
|
+
|
|
54
|
+
- [charts-pro] Fix Content-Security-Policy nonce not being correctly set on export (#20395) @bernardobelchior
|
|
55
|
+
- [charts-pro] Improve vertical zoom slider thumb on mobile (#20439) @bernardobelchior
|
|
56
|
+
- [charts-pro] Provide arguments to the `AreaPlotRoot` styled component (#20414) @arminmeh
|
|
57
|
+
- [charts-pro] Remove grid outside the drawing area (#20412) @alexfauquette
|
|
58
|
+
|
|
59
|
+
#### `@mui/x-charts-premium@8.20.0` [](https://mui.com/r/x-premium-svg-link 'Premium plan')
|
|
60
|
+
|
|
61
|
+
Same changes as in `@mui/x-charts-pro@8.20.0`, plus:
|
|
62
|
+
|
|
63
|
+
- [charts-premium] Add explicit return type to `ChartsRenderer` for better compatibility with React 18 (#20413) @arminmeh
|
|
64
|
+
|
|
65
|
+
### Docs
|
|
66
|
+
|
|
67
|
+
- [docs] Add `llms.txt` link to the sidebar (#20312) @siriwatknp
|
|
68
|
+
- [docs] Add a line chart demo for the Overview section (#20239) @prakhargupta1
|
|
69
|
+
|
|
70
|
+
## 8.19.0
|
|
71
|
+
|
|
72
|
+
_Nov 20, 2025_
|
|
73
|
+
|
|
74
|
+
We'd like to extend a big thank you to the 15 contributors who made this release possible. Here are some highlights ✨:
|
|
75
|
+
|
|
76
|
+
- 🔎 Add pan on `wheel` to the charts zoom
|
|
77
|
+
- ⌨️ Allow opt-in to [tab navigation](https://mui.com/x/react-data-grid/accessibility/#tab-navigation) inside the Data Grid.
|
|
78
|
+
- ⚙️ New way of defining [action columns](https://mui.com/x/react-data-grid/column-definition/#ActionsWithModalGrid.tsx) in the Data Grid that makes it easier to keep `columns` prop stable.
|
|
79
|
+
- 🐞 Bugfixes
|
|
80
|
+
- 📚 Documentation improvements
|
|
81
|
+
|
|
82
|
+
Special thanks go out to these community members for their valuable contributions:
|
|
83
|
+
@lauri865, @noobyogi0010, @sai6855
|
|
84
|
+
|
|
85
|
+
The following team members contributed to this release:
|
|
86
|
+
@alexfauquette, @arminmeh, @bernardobelchior, @cherniavskii, @flaviendelangle, @Janpot, @JCQuintas, @mj12albert, @noraleonte, @rita-codes, @siriwatknp, @ZeeshanTamboli
|
|
87
|
+
|
|
88
|
+
### Data Grid
|
|
89
|
+
|
|
90
|
+
#### `@mui/x-data-grid@8.19.0`
|
|
91
|
+
|
|
92
|
+
- [DataGrid] Add `tabNavigation` prop to control tab navigation in the grid (#20286) @arminmeh
|
|
93
|
+
- [DataGrid] Allow to focus disabled checkbox cells (#19959) @mj12albert
|
|
94
|
+
- [DataGrid] Alternative actions column definition API (#15041) @cherniavskii
|
|
95
|
+
- [DataGrid] Fix failing tests (#20332) @cherniavskii
|
|
96
|
+
- [DataGrid] Prevent Safari 26 error in the event handler (#20369) @arminmeh
|
|
97
|
+
- [DataGrid] Undeprecate the `autoHeight` prop (#20363) @cherniavskii
|
|
98
|
+
- [DataGrid] Fix print export grid dimensions with dynamic row height and print styles (#19835) @cherniavskii
|
|
99
|
+
|
|
100
|
+
#### `@mui/x-data-grid-pro@8.19.0` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
101
|
+
|
|
102
|
+
Same changes as in `@mui/x-data-grid@8.19.0`.
|
|
103
|
+
|
|
104
|
+
#### `@mui/x-data-grid-premium@8.19.0` [](https://mui.com/r/x-premium-svg-link 'Premium plan')
|
|
105
|
+
|
|
106
|
+
Same changes as in `@mui/x-data-grid-pro@8.19.0`, plus:
|
|
107
|
+
|
|
108
|
+
- [DataGridPremium] Fix aggregation with sorting (#19892) @lauri865
|
|
109
|
+
- [DataGridPremium] Lock `ExcelJS` version (#20329) @cherniavskii
|
|
110
|
+
|
|
111
|
+
### Date and Time Pickers
|
|
112
|
+
|
|
113
|
+
#### `@mui/x-date-pickers@8.19.0`
|
|
114
|
+
|
|
115
|
+
- [pickers] Do not loose `slotProps.field.slotProps` (#20322) @flaviendelangle
|
|
116
|
+
|
|
117
|
+
#### `@mui/x-date-pickers-pro@8.19.0` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
118
|
+
|
|
119
|
+
Same changes as in `@mui/x-date-pickers@8.19.0`.
|
|
120
|
+
|
|
121
|
+
### Charts
|
|
122
|
+
|
|
123
|
+
#### `@mui/x-charts@8.19.0`
|
|
124
|
+
|
|
125
|
+
- [charts] Expose `niceDomain` utility (#20250) @bernardobelchior
|
|
126
|
+
- [charts] Fix benchmark regression by downgrading to JSDOM v26 (#20405) @bernardobelchior
|
|
127
|
+
- [charts] Fix Pie Chart keyboard focus highlight (#20358) @JCQuintas
|
|
128
|
+
- [charts] Memoize series selectors (#20326) @JCQuintas
|
|
129
|
+
- [charts] Relax dataset type (#20294) @bernardobelchior
|
|
130
|
+
- [charts] Remove `touch-action: pan-y` when zoom is disabled (#20204) @bernardobelchior
|
|
131
|
+
- [charts] Use `getBBox()` for correct SVG sizes in firefox (#20309) @JCQuintas
|
|
132
|
+
- [charts] Use directly selector from `@mui/x-internals` (#20365) @alexfauquette
|
|
133
|
+
- [charts] Fix unnecessary errors in dev mode (#20380) @JCQuintas
|
|
134
|
+
|
|
135
|
+
#### `@mui/x-charts-pro@8.19.0` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
136
|
+
|
|
137
|
+
Same changes as in `@mui/x-charts@8.19.0`, plus:
|
|
138
|
+
|
|
139
|
+
- [charts-pro] Add pan on `wheel` to zoom (#19998) @JCQuintas
|
|
140
|
+
- [charts-pro] Fix zoom slider preview having an opaque background in dark mode (#20367) @bernardobelchior
|
|
141
|
+
|
|
142
|
+
#### `@mui/x-charts-premium@8.19.0` [](https://mui.com/r/x-premium-svg-link 'Premium plan')
|
|
143
|
+
|
|
144
|
+
Same changes as in `@mui/x-charts-pro@8.19.0`.
|
|
145
|
+
|
|
146
|
+
### Tree View
|
|
147
|
+
|
|
148
|
+
#### `@mui/x-tree-view@8.19.0`
|
|
149
|
+
|
|
150
|
+
- [tree view] Enable lazy load when children count is not know in tree view (#18680) @noobyogi0010
|
|
151
|
+
- [tree view] Fix unwanted behaviors on the item re-ordering (#20368) @flaviendelangle
|
|
152
|
+
|
|
153
|
+
#### `@mui/x-tree-view-pro@8.19.0` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
154
|
+
|
|
155
|
+
Same changes as in `@mui/x-tree-view@8.19.0`.
|
|
156
|
+
|
|
157
|
+
### Codemod
|
|
158
|
+
|
|
159
|
+
#### `@mui/x-codemod@8.19.0`
|
|
160
|
+
|
|
161
|
+
Internal changes.
|
|
162
|
+
|
|
163
|
+
### Docs
|
|
164
|
+
|
|
165
|
+
- [docs] Add minimum Typescript version to migration guide (#20320) @siriwatknp
|
|
166
|
+
- [docs] Fix Autosizing documentation (#20348) @siriwatknp
|
|
167
|
+
- [docs] Fix separator opacity in demo (#20293) @sai6855
|
|
168
|
+
- [docs] Replace deprecated `LoadingButton` with `Button` component (#20208) @Janpot
|
|
169
|
+
|
|
170
|
+
### Core
|
|
171
|
+
|
|
172
|
+
- [code-infra] Add new broken links checker (#20120) @Janpot
|
|
173
|
+
- [code-infra] Disable Codspeed pipeline (#20370) @JCQuintas
|
|
174
|
+
- [code-infra] Optimize `checkMaterialVersion` (#20307) @Janpot
|
|
175
|
+
- [code-infra] Use utils from code-infra for changelog and PR creation (#20406) @brijeshb42
|
|
176
|
+
- [docs-infra] Revert `@docsearch/react` (#20313) @Janpot
|
|
177
|
+
|
|
178
|
+
### Miscellaneous
|
|
179
|
+
|
|
180
|
+
- [test] Fix browser tests skipping some projects (#20318) @cherniavskii
|
|
181
|
+
- [test] Update `use-react-version` pnpm script (#20319) @cherniavskii
|
|
182
|
+
|
|
8
183
|
## 8.18.0
|
|
9
184
|
|
|
10
185
|
<!-- generated comparing v8.17.0..master -->
|
|
@@ -34,8 +34,8 @@ export declare namespace Dimensions {
|
|
|
34
34
|
}
|
|
35
35
|
declare function initializeState(params: VirtualizerParams): Dimensions.State;
|
|
36
36
|
declare function useDimensions(store: Store<BaseState>, params: VirtualizerParams, _api: {}): {
|
|
37
|
-
updateDimensions: () => void;
|
|
38
|
-
debouncedUpdateDimensions: ((() => void) & import("@mui/x-internals/throttle").Cancelable) | undefined;
|
|
37
|
+
updateDimensions: (firstUpdate?: boolean) => void;
|
|
38
|
+
debouncedUpdateDimensions: (((firstUpdate?: boolean) => void) & import("@mui/x-internals/throttle").Cancelable) | undefined;
|
|
39
39
|
rowsMeta: {
|
|
40
40
|
getRowHeight: (rowId: RowId) => any;
|
|
41
41
|
setLastMeasuredRowIndex: (index: number) => void;
|
|
@@ -48,4 +48,5 @@ declare function useDimensions(store: Store<BaseState>, params: VirtualizerParam
|
|
|
48
48
|
resetRowHeights: () => void;
|
|
49
49
|
};
|
|
50
50
|
};
|
|
51
|
+
export declare function observeRootNode(node: Element | null, store: Store<BaseState>, setRootSize: (size: Size) => void): (() => void) | undefined;
|
|
51
52
|
export {};
|
|
@@ -93,11 +93,14 @@ function useDimensions(store, params, _api) {
|
|
|
93
93
|
},
|
|
94
94
|
onResize
|
|
95
95
|
} = params;
|
|
96
|
-
const
|
|
97
|
-
|
|
96
|
+
const updateDimensions = React.useCallback(firstUpdate => {
|
|
97
|
+
if (firstUpdate) {
|
|
98
|
+
isFirstSizing.current = false;
|
|
99
|
+
}
|
|
98
100
|
if (isFirstSizing.current) {
|
|
99
101
|
return;
|
|
100
102
|
}
|
|
103
|
+
const containerNode = refs.container.current;
|
|
101
104
|
const rootSize = selectors.rootSize(store.state);
|
|
102
105
|
const rowsMeta = selectors.rowsMeta(store.state);
|
|
103
106
|
|
|
@@ -192,24 +195,13 @@ function useDimensions(store, params, _api) {
|
|
|
192
195
|
dimensions: newDimensions
|
|
193
196
|
});
|
|
194
197
|
onResize?.(newDimensions.root);
|
|
195
|
-
}, [store,
|
|
198
|
+
}, [store, refs.container, params.dimensions.scrollbarSize, params.autoHeight, params.disableHorizontalScroll, params.disableVerticalScroll, onResize, rowHeight, columnsTotalWidth, leftPinnedWidth, rightPinnedWidth, topPinnedHeight, bottomPinnedHeight]);
|
|
196
199
|
const {
|
|
197
200
|
resizeThrottleMs
|
|
198
201
|
} = params;
|
|
199
202
|
const updateDimensionCallback = useEventCallback(updateDimensions);
|
|
200
203
|
const debouncedUpdateDimensions = React.useMemo(() => resizeThrottleMs > 0 ? throttle(updateDimensionCallback, resizeThrottleMs) : undefined, [resizeThrottleMs, updateDimensionCallback]);
|
|
201
204
|
React.useEffect(() => debouncedUpdateDimensions?.clear, [debouncedUpdateDimensions]);
|
|
202
|
-
const setRootSize = useEventCallback(rootSize => {
|
|
203
|
-
store.state.rootSize = rootSize;
|
|
204
|
-
if (isFirstSizing.current || !debouncedUpdateDimensions) {
|
|
205
|
-
// We want to initialize the grid dimensions as soon as possible to avoid flickering
|
|
206
|
-
isFirstSizing.current = false;
|
|
207
|
-
updateDimensions();
|
|
208
|
-
} else {
|
|
209
|
-
debouncedUpdateDimensions();
|
|
210
|
-
}
|
|
211
|
-
});
|
|
212
|
-
useLayoutEffect(() => observeRootNode(containerNode, store, setRootSize), [containerNode, store, setRootSize]);
|
|
213
205
|
useLayoutEffect(updateDimensions, [updateDimensions]);
|
|
214
206
|
const rowsMeta = useRowsMeta(store, params, updateDimensions);
|
|
215
207
|
return {
|
|
@@ -392,7 +384,7 @@ function useRowsMeta(store, params, updateDimensions) {
|
|
|
392
384
|
resetRowHeights
|
|
393
385
|
};
|
|
394
386
|
}
|
|
395
|
-
function observeRootNode(node, store, setRootSize) {
|
|
387
|
+
export function observeRootNode(node, store, setRootSize) {
|
|
396
388
|
if (!node) {
|
|
397
389
|
return undefined;
|
|
398
390
|
}
|
|
@@ -31,6 +31,7 @@ export declare const Virtualization: {
|
|
|
31
31
|
initialize: typeof initializeState;
|
|
32
32
|
use: typeof useVirtualization;
|
|
33
33
|
selectors: {
|
|
34
|
+
store: (state: BaseState) => VirtualizationState;
|
|
34
35
|
renderContext: (state: BaseState) => RenderContext;
|
|
35
36
|
enabledForRows: (state: BaseState) => boolean;
|
|
36
37
|
enabledForColumns: (state: BaseState) => boolean;
|
|
@@ -60,14 +61,12 @@ declare function useVirtualization(store: Store<BaseState>, params: VirtualizerP
|
|
|
60
61
|
position?: PinnedRowPosition;
|
|
61
62
|
renderContext?: RenderContext;
|
|
62
63
|
}, unstable_rowTree?: Record<RowId, any>) => React.ReactNode[];
|
|
64
|
+
rows: RowEntry[];
|
|
63
65
|
getContainerProps: () => {
|
|
64
|
-
ref: (node: HTMLDivElement | null) => void;
|
|
66
|
+
ref: (node: HTMLDivElement | null) => (() => void | undefined) | undefined;
|
|
65
67
|
};
|
|
66
68
|
getScrollerProps: () => {
|
|
67
|
-
ref: (node: HTMLDivElement | null) => void;
|
|
68
|
-
onScroll: () => void;
|
|
69
|
-
onWheel: ((event: React.WheelEvent) => void) | undefined;
|
|
70
|
-
onTouchMove: ((event: React.TouchEvent) => void) | undefined;
|
|
69
|
+
ref: (node: HTMLDivElement | null) => (() => void | undefined) | undefined;
|
|
71
70
|
style: React.CSSProperties;
|
|
72
71
|
role: string;
|
|
73
72
|
tabIndex: number | undefined;
|
|
@@ -101,6 +100,7 @@ declare function useVirtualization(store: Store<BaseState>, params: VirtualizerP
|
|
|
101
100
|
useVirtualization: () => BaseState;
|
|
102
101
|
setPanels: React.Dispatch<React.SetStateAction<Readonly<Map<any, React.ReactNode>>>>;
|
|
103
102
|
forceUpdateRenderContext: () => void;
|
|
103
|
+
scheduleUpdateRenderContext: () => void;
|
|
104
104
|
getCellColSpanInfo: (rowId: RowId, columnIndex: integer) => CellColSpanInfo;
|
|
105
105
|
calculateColSpan: (rowId: RowId, minFirstColumn: integer, maxLastColumn: integer, columns: ColumnWithWidth[]) => void;
|
|
106
106
|
getHiddenCellsOrigin: () => Record<RowId, Record<number, number>>;
|
|
@@ -9,10 +9,10 @@ import useEventCallback from '@mui/utils/useEventCallback';
|
|
|
9
9
|
import useEnhancedEffect from '@mui/utils/useEnhancedEffect';
|
|
10
10
|
import * as platform from '@mui/x-internals/platform';
|
|
11
11
|
import { useRunOnce } from '@mui/x-internals/useRunOnce';
|
|
12
|
-
import { useFirstRender } from '@mui/x-internals/useFirstRender';
|
|
13
12
|
import { createSelector, useStore, useStoreEffect } from '@mui/x-internals/store';
|
|
13
|
+
import reactMajor from '@mui/x-internals/reactMajor';
|
|
14
14
|
import { PinnedRows, PinnedColumns } from "../models/core.js";
|
|
15
|
-
import { Dimensions } from "./dimensions.js";
|
|
15
|
+
import { Dimensions, observeRootNode } from "./dimensions.js";
|
|
16
16
|
import { ScrollDirection } from "../models/index.js";
|
|
17
17
|
|
|
18
18
|
/* eslint-disable import/export, @typescript-eslint/no-redeclare */
|
|
@@ -31,6 +31,7 @@ export const EMPTY_RENDER_CONTEXT = {
|
|
|
31
31
|
lastColumnIndex: 0
|
|
32
32
|
};
|
|
33
33
|
const selectors = {
|
|
34
|
+
store: createSelector(state => state.virtualization),
|
|
34
35
|
renderContext: createSelector(state => state.virtualization.renderContext),
|
|
35
36
|
enabledForRows: createSelector(state => state.virtualization.enabledForRows),
|
|
36
37
|
enabledForColumns: createSelector(state => state.virtualization.enabledForColumns)
|
|
@@ -88,7 +89,7 @@ function useVirtualization(store, params, api) {
|
|
|
88
89
|
const needsHorizontalScrollbar = useStore(store, Dimensions.selectors.needsHorizontalScrollbar);
|
|
89
90
|
const hasBottomPinnedRows = pinnedRows.bottom.length > 0;
|
|
90
91
|
const [panels, setPanels] = React.useState(EMPTY_DETAIL_PANELS);
|
|
91
|
-
const
|
|
92
|
+
const isUpdateScheduled = React.useRef(false);
|
|
92
93
|
const isRenderContextReady = React.useRef(false);
|
|
93
94
|
const renderContext = useStore(store, selectors.renderContext);
|
|
94
95
|
const enabledForRows = useStore(store, selectors.enabledForRows);
|
|
@@ -148,7 +149,7 @@ function useVirtualization(store, params, api) {
|
|
|
148
149
|
// Clamp the scroll position to the viewport to avoid re-calculating the render context for scroll bounce
|
|
149
150
|
const newScroll = {
|
|
150
151
|
top: clamp(scroller.scrollTop, 0, maxScrollTop),
|
|
151
|
-
left: isRtl ? clamp(scroller.scrollLeft, -maxScrollLeft, 0) : clamp(scroller.scrollLeft, 0, maxScrollLeft)
|
|
152
|
+
left: isRtl ? clamp(scroller.scrollLeft, -Math.abs(maxScrollLeft), 0) : clamp(scroller.scrollLeft, 0, maxScrollLeft)
|
|
152
153
|
};
|
|
153
154
|
const dx = newScroll.left - scrollPosition.current.left;
|
|
154
155
|
const dy = newScroll.top - scrollPosition.current.top;
|
|
@@ -195,7 +196,7 @@ function useVirtualization(store, params, api) {
|
|
|
195
196
|
}
|
|
196
197
|
return nextRenderContext;
|
|
197
198
|
});
|
|
198
|
-
const forceUpdateRenderContext =
|
|
199
|
+
const forceUpdateRenderContext = () => {
|
|
199
200
|
// skip update if dimensions are not ready and virtualization is enabled
|
|
200
201
|
if (!Dimensions.selectors.dimensions(store.state).isReady && (enabledForRows || enabledForColumns)) {
|
|
201
202
|
return;
|
|
@@ -205,7 +206,22 @@ function useVirtualization(store, params, api) {
|
|
|
205
206
|
// Reset the frozen context when the render context changes, see the illustration in https://github.com/mui/mui-x/pull/12353
|
|
206
207
|
frozenContext.current = undefined;
|
|
207
208
|
updateRenderContext(nextRenderContext);
|
|
209
|
+
};
|
|
210
|
+
const forceUpdateRenderContextCallback = useEventCallback(forceUpdateRenderContext);
|
|
211
|
+
useStoreEffect(store, Dimensions.selectors.dimensions, (previous, next) => {
|
|
212
|
+
if (next.isReady) {
|
|
213
|
+
forceUpdateRenderContext();
|
|
214
|
+
}
|
|
208
215
|
});
|
|
216
|
+
useEnhancedEffect(() => {
|
|
217
|
+
if (isUpdateScheduled.current) {
|
|
218
|
+
forceUpdateRenderContext();
|
|
219
|
+
isUpdateScheduled.current = false;
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
const scheduleUpdateRenderContext = () => {
|
|
223
|
+
isUpdateScheduled.current = true;
|
|
224
|
+
};
|
|
209
225
|
const handleScroll = useEventCallback(() => {
|
|
210
226
|
if (ignoreNextScrollEvent.current) {
|
|
211
227
|
ignoreNextScrollEvent.current = false;
|
|
@@ -379,8 +395,8 @@ function useVirtualization(store, params, api) {
|
|
|
379
395
|
if (!isRenderContextReady.current) {
|
|
380
396
|
return;
|
|
381
397
|
}
|
|
382
|
-
|
|
383
|
-
}, [enabledForColumns, enabledForRows,
|
|
398
|
+
forceUpdateRenderContextCallback();
|
|
399
|
+
}, [enabledForColumns, enabledForRows, forceUpdateRenderContextCallback]);
|
|
384
400
|
useEnhancedEffect(() => {
|
|
385
401
|
if (refs.scroller.current) {
|
|
386
402
|
refs.scroller.current.scrollLeft = 0;
|
|
@@ -436,21 +452,77 @@ function useVirtualization(store, params, api) {
|
|
|
436
452
|
const refSetter = name => node => {
|
|
437
453
|
if (node && refs[name].current !== node) {
|
|
438
454
|
refs[name].current = node;
|
|
439
|
-
setRefTick(tick => tick + 1);
|
|
440
455
|
}
|
|
441
456
|
};
|
|
457
|
+
const isFirstSizing = React.useRef(true);
|
|
458
|
+
const containerCleanup = React.useRef(undefined);
|
|
459
|
+
const containerRef = useEventCallback(node => {
|
|
460
|
+
if (!node) {
|
|
461
|
+
// Cleanup for R18
|
|
462
|
+
containerCleanup.current?.();
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
refs.container.current = node;
|
|
466
|
+
const unsubscribe = observeRootNode(node, store, rootSize => {
|
|
467
|
+
if (rootSize.width === 0 && rootSize.height === 0 && store.state.rootSize.height !== 0 && store.state.rootSize.width !== 0) {
|
|
468
|
+
return;
|
|
469
|
+
}
|
|
470
|
+
store.state.rootSize = rootSize;
|
|
471
|
+
if (isFirstSizing.current || !api.debouncedUpdateDimensions) {
|
|
472
|
+
// We want to initialize the grid dimensions as soon as possible to avoid flickering
|
|
473
|
+
api.updateDimensions(isFirstSizing.current);
|
|
474
|
+
isFirstSizing.current = false;
|
|
475
|
+
} else {
|
|
476
|
+
api.debouncedUpdateDimensions();
|
|
477
|
+
}
|
|
478
|
+
});
|
|
479
|
+
containerCleanup.current = () => {
|
|
480
|
+
unsubscribe?.();
|
|
481
|
+
refs.container.current = null;
|
|
482
|
+
};
|
|
483
|
+
if (reactMajor >= 19) {
|
|
484
|
+
/* eslint-disable-next-line consistent-return */
|
|
485
|
+
return containerCleanup.current;
|
|
486
|
+
}
|
|
487
|
+
});
|
|
488
|
+
const scrollerCleanup = React.useRef(undefined);
|
|
489
|
+
const scrollerRef = useEventCallback(node => {
|
|
490
|
+
if (!node) {
|
|
491
|
+
// Cleanup for R18
|
|
492
|
+
scrollerCleanup.current?.();
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
scrollerCleanup.current?.();
|
|
496
|
+
refs.scroller.current = node;
|
|
497
|
+
const opts = {
|
|
498
|
+
passive: true
|
|
499
|
+
};
|
|
500
|
+
node.addEventListener('scroll', handleScroll, opts);
|
|
501
|
+
node.addEventListener('wheel', onWheel, opts);
|
|
502
|
+
node.addEventListener('touchmove', onTouchMove, opts);
|
|
503
|
+
scrollerCleanup.current = () => {
|
|
504
|
+
node.removeEventListener('scroll', handleScroll, opts);
|
|
505
|
+
node.removeEventListener('wheel', onWheel, opts);
|
|
506
|
+
node.removeEventListener('touchmove', onTouchMove, opts);
|
|
507
|
+
refs.scroller.current = null;
|
|
508
|
+
};
|
|
509
|
+
if (reactMajor >= 19) {
|
|
510
|
+
/* eslint-disable-next-line consistent-return */
|
|
511
|
+
return scrollerCleanup.current;
|
|
512
|
+
}
|
|
513
|
+
});
|
|
514
|
+
const scrollbarVerticalRef = useEventCallback(refSetter('scrollbarVertical'));
|
|
515
|
+
const scrollbarHorizontalRef = useEventCallback(refSetter('scrollbarHorizontal'));
|
|
442
516
|
const getters = {
|
|
443
517
|
setPanels,
|
|
444
518
|
getOffsetTop,
|
|
445
519
|
getRows,
|
|
520
|
+
rows: params.rows,
|
|
446
521
|
getContainerProps: () => ({
|
|
447
|
-
ref:
|
|
522
|
+
ref: containerRef
|
|
448
523
|
}),
|
|
449
524
|
getScrollerProps: () => ({
|
|
450
|
-
ref:
|
|
451
|
-
onScroll: handleScroll,
|
|
452
|
-
onWheel,
|
|
453
|
-
onTouchMove,
|
|
525
|
+
ref: scrollerRef,
|
|
454
526
|
style: scrollerStyle,
|
|
455
527
|
role: 'presentation',
|
|
456
528
|
// `tabIndex` shouldn't be used along role=presentation, but it fixes a Firefox bug
|
|
@@ -463,28 +535,17 @@ function useVirtualization(store, params, api) {
|
|
|
463
535
|
role: 'presentation'
|
|
464
536
|
}),
|
|
465
537
|
getScrollbarVerticalProps: () => ({
|
|
466
|
-
ref:
|
|
538
|
+
ref: scrollbarVerticalRef,
|
|
467
539
|
scrollPosition
|
|
468
540
|
}),
|
|
469
541
|
getScrollbarHorizontalProps: () => ({
|
|
470
|
-
ref:
|
|
542
|
+
ref: scrollbarHorizontalRef,
|
|
471
543
|
scrollPosition
|
|
472
544
|
}),
|
|
473
545
|
getScrollAreaProps: () => ({
|
|
474
546
|
scrollPosition
|
|
475
547
|
})
|
|
476
548
|
};
|
|
477
|
-
useFirstRender(() => {
|
|
478
|
-
store.state = _extends({}, store.state, {
|
|
479
|
-
getters
|
|
480
|
-
});
|
|
481
|
-
});
|
|
482
|
-
React.useEffect(() => {
|
|
483
|
-
store.update({
|
|
484
|
-
getters
|
|
485
|
-
});
|
|
486
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
487
|
-
}, Object.values(getters));
|
|
488
549
|
|
|
489
550
|
/* Placeholder API functions for colspan & rowspan to re-implement */
|
|
490
551
|
|
|
@@ -502,6 +563,7 @@ function useVirtualization(store, params, api) {
|
|
|
502
563
|
useVirtualization: () => useStore(store, state => state),
|
|
503
564
|
setPanels,
|
|
504
565
|
forceUpdateRenderContext,
|
|
566
|
+
scheduleUpdateRenderContext,
|
|
505
567
|
getCellColSpanInfo,
|
|
506
568
|
calculateColSpan,
|
|
507
569
|
getHiddenCellsOrigin
|
|
@@ -577,7 +639,6 @@ function computeRenderContext(inputs, scrollPosition, scrollCache) {
|
|
|
577
639
|
// lastColumnIndex: 1,
|
|
578
640
|
// };
|
|
579
641
|
// }
|
|
580
|
-
|
|
581
642
|
if (inputs.enabledForColumns) {
|
|
582
643
|
let firstColumnIndex = 0;
|
|
583
644
|
let lastColumnIndex = inputs.columnPositions.length;
|
package/esm/index.js
CHANGED
package/esm/useVirtualizer.d.ts
CHANGED
|
@@ -99,8 +99,8 @@ export type VirtualizerParams = {
|
|
|
99
99
|
export declare const useVirtualizer: (params: VirtualizerParams) => {
|
|
100
100
|
store: Store<Dimensions.State & Virtualization.State & Colspan.State & Rowspan.State>;
|
|
101
101
|
api: {
|
|
102
|
-
updateDimensions: () => void;
|
|
103
|
-
debouncedUpdateDimensions: ((() => void) & import("@mui/x-internals/throttle").Cancelable) | undefined;
|
|
102
|
+
updateDimensions: (firstUpdate?: boolean) => void;
|
|
103
|
+
debouncedUpdateDimensions: (((firstUpdate?: boolean) => void) & import("@mui/x-internals/throttle").Cancelable) | undefined;
|
|
104
104
|
rowsMeta: {
|
|
105
105
|
getRowHeight: (rowId: import("./models/index.js").RowId) => any;
|
|
106
106
|
setLastMeasuredRowIndex: (index: number) => void;
|
|
@@ -121,14 +121,12 @@ export declare const useVirtualizer: (params: VirtualizerParams) => {
|
|
|
121
121
|
position?: import("./models/index.js").PinnedRowPosition;
|
|
122
122
|
renderContext?: RenderContext;
|
|
123
123
|
}, unstable_rowTree?: Record<import("./models/index.js").RowId, any>) => React.ReactNode[];
|
|
124
|
+
rows: RowEntry[];
|
|
124
125
|
getContainerProps: () => {
|
|
125
|
-
ref: (node: HTMLDivElement | null) => void;
|
|
126
|
+
ref: (node: HTMLDivElement | null) => (() => void | undefined) | undefined;
|
|
126
127
|
};
|
|
127
128
|
getScrollerProps: () => {
|
|
128
|
-
ref: (node: HTMLDivElement | null) => void;
|
|
129
|
-
onScroll: () => void;
|
|
130
|
-
onWheel: ((event: React.WheelEvent) => void) | undefined;
|
|
131
|
-
onTouchMove: ((event: React.TouchEvent) => void) | undefined;
|
|
129
|
+
ref: (node: HTMLDivElement | null) => (() => void | undefined) | undefined;
|
|
132
130
|
style: React.CSSProperties;
|
|
133
131
|
role: string;
|
|
134
132
|
tabIndex: number | undefined;
|
|
@@ -162,6 +160,7 @@ export declare const useVirtualizer: (params: VirtualizerParams) => {
|
|
|
162
160
|
useVirtualization: () => BaseState;
|
|
163
161
|
setPanels: React.Dispatch<React.SetStateAction<Readonly<Map<any, React.ReactNode>>>>;
|
|
164
162
|
forceUpdateRenderContext: () => void;
|
|
163
|
+
scheduleUpdateRenderContext: () => void;
|
|
165
164
|
getCellColSpanInfo: (rowId: import("./models/index.js").RowId, columnIndex: integer) => import("./models/index.js").CellColSpanInfo;
|
|
166
165
|
calculateColSpan: (rowId: import("./models/index.js").RowId, minFirstColumn: integer, maxLastColumn: integer, columns: ColumnWithWidth[]) => void;
|
|
167
166
|
getHiddenCellsOrigin: () => Record<import("./models/index.js").RowId, Record<number, number>>;
|
package/features/dimensions.d.ts
CHANGED
|
@@ -34,8 +34,8 @@ export declare namespace Dimensions {
|
|
|
34
34
|
}
|
|
35
35
|
declare function initializeState(params: VirtualizerParams): Dimensions.State;
|
|
36
36
|
declare function useDimensions(store: Store<BaseState>, params: VirtualizerParams, _api: {}): {
|
|
37
|
-
updateDimensions: () => void;
|
|
38
|
-
debouncedUpdateDimensions: ((() => void) & import("@mui/x-internals/throttle").Cancelable) | undefined;
|
|
37
|
+
updateDimensions: (firstUpdate?: boolean) => void;
|
|
38
|
+
debouncedUpdateDimensions: (((firstUpdate?: boolean) => void) & import("@mui/x-internals/throttle").Cancelable) | undefined;
|
|
39
39
|
rowsMeta: {
|
|
40
40
|
getRowHeight: (rowId: RowId) => any;
|
|
41
41
|
setLastMeasuredRowIndex: (index: number) => void;
|
|
@@ -48,4 +48,5 @@ declare function useDimensions(store: Store<BaseState>, params: VirtualizerParam
|
|
|
48
48
|
resetRowHeights: () => void;
|
|
49
49
|
};
|
|
50
50
|
};
|
|
51
|
+
export declare function observeRootNode(node: Element | null, store: Store<BaseState>, setRootSize: (size: Size) => void): (() => void) | undefined;
|
|
51
52
|
export {};
|
package/features/dimensions.js
CHANGED
|
@@ -7,6 +7,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
7
7
|
value: true
|
|
8
8
|
});
|
|
9
9
|
exports.Dimensions = void 0;
|
|
10
|
+
exports.observeRootNode = observeRootNode;
|
|
10
11
|
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
|
|
11
12
|
var React = _interopRequireWildcard(require("react"));
|
|
12
13
|
var _ownerDocument = _interopRequireDefault(require("@mui/utils/ownerDocument"));
|
|
@@ -99,11 +100,14 @@ function useDimensions(store, params, _api) {
|
|
|
99
100
|
},
|
|
100
101
|
onResize
|
|
101
102
|
} = params;
|
|
102
|
-
const
|
|
103
|
-
|
|
103
|
+
const updateDimensions = React.useCallback(firstUpdate => {
|
|
104
|
+
if (firstUpdate) {
|
|
105
|
+
isFirstSizing.current = false;
|
|
106
|
+
}
|
|
104
107
|
if (isFirstSizing.current) {
|
|
105
108
|
return;
|
|
106
109
|
}
|
|
110
|
+
const containerNode = refs.container.current;
|
|
107
111
|
const rootSize = selectors.rootSize(store.state);
|
|
108
112
|
const rowsMeta = selectors.rowsMeta(store.state);
|
|
109
113
|
|
|
@@ -198,24 +202,13 @@ function useDimensions(store, params, _api) {
|
|
|
198
202
|
dimensions: newDimensions
|
|
199
203
|
});
|
|
200
204
|
onResize?.(newDimensions.root);
|
|
201
|
-
}, [store,
|
|
205
|
+
}, [store, refs.container, params.dimensions.scrollbarSize, params.autoHeight, params.disableHorizontalScroll, params.disableVerticalScroll, onResize, rowHeight, columnsTotalWidth, leftPinnedWidth, rightPinnedWidth, topPinnedHeight, bottomPinnedHeight]);
|
|
202
206
|
const {
|
|
203
207
|
resizeThrottleMs
|
|
204
208
|
} = params;
|
|
205
209
|
const updateDimensionCallback = (0, _useEventCallback.default)(updateDimensions);
|
|
206
210
|
const debouncedUpdateDimensions = React.useMemo(() => resizeThrottleMs > 0 ? (0, _throttle.throttle)(updateDimensionCallback, resizeThrottleMs) : undefined, [resizeThrottleMs, updateDimensionCallback]);
|
|
207
211
|
React.useEffect(() => debouncedUpdateDimensions?.clear, [debouncedUpdateDimensions]);
|
|
208
|
-
const setRootSize = (0, _useEventCallback.default)(rootSize => {
|
|
209
|
-
store.state.rootSize = rootSize;
|
|
210
|
-
if (isFirstSizing.current || !debouncedUpdateDimensions) {
|
|
211
|
-
// We want to initialize the grid dimensions as soon as possible to avoid flickering
|
|
212
|
-
isFirstSizing.current = false;
|
|
213
|
-
updateDimensions();
|
|
214
|
-
} else {
|
|
215
|
-
debouncedUpdateDimensions();
|
|
216
|
-
}
|
|
217
|
-
});
|
|
218
|
-
(0, _useEnhancedEffect.default)(() => observeRootNode(containerNode, store, setRootSize), [containerNode, store, setRootSize]);
|
|
219
212
|
(0, _useEnhancedEffect.default)(updateDimensions, [updateDimensions]);
|
|
220
213
|
const rowsMeta = useRowsMeta(store, params, updateDimensions);
|
|
221
214
|
return {
|
|
@@ -31,6 +31,7 @@ export declare const Virtualization: {
|
|
|
31
31
|
initialize: typeof initializeState;
|
|
32
32
|
use: typeof useVirtualization;
|
|
33
33
|
selectors: {
|
|
34
|
+
store: (state: BaseState) => VirtualizationState;
|
|
34
35
|
renderContext: (state: BaseState) => RenderContext;
|
|
35
36
|
enabledForRows: (state: BaseState) => boolean;
|
|
36
37
|
enabledForColumns: (state: BaseState) => boolean;
|
|
@@ -60,14 +61,12 @@ declare function useVirtualization(store: Store<BaseState>, params: VirtualizerP
|
|
|
60
61
|
position?: PinnedRowPosition;
|
|
61
62
|
renderContext?: RenderContext;
|
|
62
63
|
}, unstable_rowTree?: Record<RowId, any>) => React.ReactNode[];
|
|
64
|
+
rows: RowEntry[];
|
|
63
65
|
getContainerProps: () => {
|
|
64
|
-
ref: (node: HTMLDivElement | null) => void;
|
|
66
|
+
ref: (node: HTMLDivElement | null) => (() => void | undefined) | undefined;
|
|
65
67
|
};
|
|
66
68
|
getScrollerProps: () => {
|
|
67
|
-
ref: (node: HTMLDivElement | null) => void;
|
|
68
|
-
onScroll: () => void;
|
|
69
|
-
onWheel: ((event: React.WheelEvent) => void) | undefined;
|
|
70
|
-
onTouchMove: ((event: React.TouchEvent) => void) | undefined;
|
|
69
|
+
ref: (node: HTMLDivElement | null) => (() => void | undefined) | undefined;
|
|
71
70
|
style: React.CSSProperties;
|
|
72
71
|
role: string;
|
|
73
72
|
tabIndex: number | undefined;
|
|
@@ -101,6 +100,7 @@ declare function useVirtualization(store: Store<BaseState>, params: VirtualizerP
|
|
|
101
100
|
useVirtualization: () => BaseState;
|
|
102
101
|
setPanels: React.Dispatch<React.SetStateAction<Readonly<Map<any, React.ReactNode>>>>;
|
|
103
102
|
forceUpdateRenderContext: () => void;
|
|
103
|
+
scheduleUpdateRenderContext: () => void;
|
|
104
104
|
getCellColSpanInfo: (rowId: RowId, columnIndex: integer) => CellColSpanInfo;
|
|
105
105
|
calculateColSpan: (rowId: RowId, minFirstColumn: integer, maxLastColumn: integer, columns: ColumnWithWidth[]) => void;
|
|
106
106
|
getHiddenCellsOrigin: () => Record<RowId, Record<number, number>>;
|
|
@@ -19,8 +19,8 @@ var _useEventCallback = _interopRequireDefault(require("@mui/utils/useEventCallb
|
|
|
19
19
|
var _useEnhancedEffect = _interopRequireDefault(require("@mui/utils/useEnhancedEffect"));
|
|
20
20
|
var platform = _interopRequireWildcard(require("@mui/x-internals/platform"));
|
|
21
21
|
var _useRunOnce = require("@mui/x-internals/useRunOnce");
|
|
22
|
-
var _useFirstRender = require("@mui/x-internals/useFirstRender");
|
|
23
22
|
var _store = require("@mui/x-internals/store");
|
|
23
|
+
var _reactMajor = _interopRequireDefault(require("@mui/x-internals/reactMajor"));
|
|
24
24
|
var _core = require("../models/core");
|
|
25
25
|
var _dimensions = require("./dimensions");
|
|
26
26
|
var _models = require("../models");
|
|
@@ -40,6 +40,7 @@ const EMPTY_RENDER_CONTEXT = exports.EMPTY_RENDER_CONTEXT = {
|
|
|
40
40
|
lastColumnIndex: 0
|
|
41
41
|
};
|
|
42
42
|
const selectors = {
|
|
43
|
+
store: (0, _store.createSelector)(state => state.virtualization),
|
|
43
44
|
renderContext: (0, _store.createSelector)(state => state.virtualization.renderContext),
|
|
44
45
|
enabledForRows: (0, _store.createSelector)(state => state.virtualization.enabledForRows),
|
|
45
46
|
enabledForColumns: (0, _store.createSelector)(state => state.virtualization.enabledForColumns)
|
|
@@ -97,7 +98,7 @@ function useVirtualization(store, params, api) {
|
|
|
97
98
|
const needsHorizontalScrollbar = (0, _store.useStore)(store, _dimensions.Dimensions.selectors.needsHorizontalScrollbar);
|
|
98
99
|
const hasBottomPinnedRows = pinnedRows.bottom.length > 0;
|
|
99
100
|
const [panels, setPanels] = React.useState(EMPTY_DETAIL_PANELS);
|
|
100
|
-
const
|
|
101
|
+
const isUpdateScheduled = React.useRef(false);
|
|
101
102
|
const isRenderContextReady = React.useRef(false);
|
|
102
103
|
const renderContext = (0, _store.useStore)(store, selectors.renderContext);
|
|
103
104
|
const enabledForRows = (0, _store.useStore)(store, selectors.enabledForRows);
|
|
@@ -157,7 +158,7 @@ function useVirtualization(store, params, api) {
|
|
|
157
158
|
// Clamp the scroll position to the viewport to avoid re-calculating the render context for scroll bounce
|
|
158
159
|
const newScroll = {
|
|
159
160
|
top: clamp(scroller.scrollTop, 0, maxScrollTop),
|
|
160
|
-
left: isRtl ? clamp(scroller.scrollLeft, -maxScrollLeft, 0) : clamp(scroller.scrollLeft, 0, maxScrollLeft)
|
|
161
|
+
left: isRtl ? clamp(scroller.scrollLeft, -Math.abs(maxScrollLeft), 0) : clamp(scroller.scrollLeft, 0, maxScrollLeft)
|
|
161
162
|
};
|
|
162
163
|
const dx = newScroll.left - scrollPosition.current.left;
|
|
163
164
|
const dy = newScroll.top - scrollPosition.current.top;
|
|
@@ -204,7 +205,7 @@ function useVirtualization(store, params, api) {
|
|
|
204
205
|
}
|
|
205
206
|
return nextRenderContext;
|
|
206
207
|
});
|
|
207
|
-
const forceUpdateRenderContext = (
|
|
208
|
+
const forceUpdateRenderContext = () => {
|
|
208
209
|
// skip update if dimensions are not ready and virtualization is enabled
|
|
209
210
|
if (!_dimensions.Dimensions.selectors.dimensions(store.state).isReady && (enabledForRows || enabledForColumns)) {
|
|
210
211
|
return;
|
|
@@ -214,7 +215,22 @@ function useVirtualization(store, params, api) {
|
|
|
214
215
|
// Reset the frozen context when the render context changes, see the illustration in https://github.com/mui/mui-x/pull/12353
|
|
215
216
|
frozenContext.current = undefined;
|
|
216
217
|
updateRenderContext(nextRenderContext);
|
|
218
|
+
};
|
|
219
|
+
const forceUpdateRenderContextCallback = (0, _useEventCallback.default)(forceUpdateRenderContext);
|
|
220
|
+
(0, _store.useStoreEffect)(store, _dimensions.Dimensions.selectors.dimensions, (previous, next) => {
|
|
221
|
+
if (next.isReady) {
|
|
222
|
+
forceUpdateRenderContext();
|
|
223
|
+
}
|
|
217
224
|
});
|
|
225
|
+
(0, _useEnhancedEffect.default)(() => {
|
|
226
|
+
if (isUpdateScheduled.current) {
|
|
227
|
+
forceUpdateRenderContext();
|
|
228
|
+
isUpdateScheduled.current = false;
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
const scheduleUpdateRenderContext = () => {
|
|
232
|
+
isUpdateScheduled.current = true;
|
|
233
|
+
};
|
|
218
234
|
const handleScroll = (0, _useEventCallback.default)(() => {
|
|
219
235
|
if (ignoreNextScrollEvent.current) {
|
|
220
236
|
ignoreNextScrollEvent.current = false;
|
|
@@ -388,8 +404,8 @@ function useVirtualization(store, params, api) {
|
|
|
388
404
|
if (!isRenderContextReady.current) {
|
|
389
405
|
return;
|
|
390
406
|
}
|
|
391
|
-
|
|
392
|
-
}, [enabledForColumns, enabledForRows,
|
|
407
|
+
forceUpdateRenderContextCallback();
|
|
408
|
+
}, [enabledForColumns, enabledForRows, forceUpdateRenderContextCallback]);
|
|
393
409
|
(0, _useEnhancedEffect.default)(() => {
|
|
394
410
|
if (refs.scroller.current) {
|
|
395
411
|
refs.scroller.current.scrollLeft = 0;
|
|
@@ -445,21 +461,77 @@ function useVirtualization(store, params, api) {
|
|
|
445
461
|
const refSetter = name => node => {
|
|
446
462
|
if (node && refs[name].current !== node) {
|
|
447
463
|
refs[name].current = node;
|
|
448
|
-
setRefTick(tick => tick + 1);
|
|
449
464
|
}
|
|
450
465
|
};
|
|
466
|
+
const isFirstSizing = React.useRef(true);
|
|
467
|
+
const containerCleanup = React.useRef(undefined);
|
|
468
|
+
const containerRef = (0, _useEventCallback.default)(node => {
|
|
469
|
+
if (!node) {
|
|
470
|
+
// Cleanup for R18
|
|
471
|
+
containerCleanup.current?.();
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
refs.container.current = node;
|
|
475
|
+
const unsubscribe = (0, _dimensions.observeRootNode)(node, store, rootSize => {
|
|
476
|
+
if (rootSize.width === 0 && rootSize.height === 0 && store.state.rootSize.height !== 0 && store.state.rootSize.width !== 0) {
|
|
477
|
+
return;
|
|
478
|
+
}
|
|
479
|
+
store.state.rootSize = rootSize;
|
|
480
|
+
if (isFirstSizing.current || !api.debouncedUpdateDimensions) {
|
|
481
|
+
// We want to initialize the grid dimensions as soon as possible to avoid flickering
|
|
482
|
+
api.updateDimensions(isFirstSizing.current);
|
|
483
|
+
isFirstSizing.current = false;
|
|
484
|
+
} else {
|
|
485
|
+
api.debouncedUpdateDimensions();
|
|
486
|
+
}
|
|
487
|
+
});
|
|
488
|
+
containerCleanup.current = () => {
|
|
489
|
+
unsubscribe?.();
|
|
490
|
+
refs.container.current = null;
|
|
491
|
+
};
|
|
492
|
+
if (_reactMajor.default >= 19) {
|
|
493
|
+
/* eslint-disable-next-line consistent-return */
|
|
494
|
+
return containerCleanup.current;
|
|
495
|
+
}
|
|
496
|
+
});
|
|
497
|
+
const scrollerCleanup = React.useRef(undefined);
|
|
498
|
+
const scrollerRef = (0, _useEventCallback.default)(node => {
|
|
499
|
+
if (!node) {
|
|
500
|
+
// Cleanup for R18
|
|
501
|
+
scrollerCleanup.current?.();
|
|
502
|
+
return;
|
|
503
|
+
}
|
|
504
|
+
scrollerCleanup.current?.();
|
|
505
|
+
refs.scroller.current = node;
|
|
506
|
+
const opts = {
|
|
507
|
+
passive: true
|
|
508
|
+
};
|
|
509
|
+
node.addEventListener('scroll', handleScroll, opts);
|
|
510
|
+
node.addEventListener('wheel', onWheel, opts);
|
|
511
|
+
node.addEventListener('touchmove', onTouchMove, opts);
|
|
512
|
+
scrollerCleanup.current = () => {
|
|
513
|
+
node.removeEventListener('scroll', handleScroll, opts);
|
|
514
|
+
node.removeEventListener('wheel', onWheel, opts);
|
|
515
|
+
node.removeEventListener('touchmove', onTouchMove, opts);
|
|
516
|
+
refs.scroller.current = null;
|
|
517
|
+
};
|
|
518
|
+
if (_reactMajor.default >= 19) {
|
|
519
|
+
/* eslint-disable-next-line consistent-return */
|
|
520
|
+
return scrollerCleanup.current;
|
|
521
|
+
}
|
|
522
|
+
});
|
|
523
|
+
const scrollbarVerticalRef = (0, _useEventCallback.default)(refSetter('scrollbarVertical'));
|
|
524
|
+
const scrollbarHorizontalRef = (0, _useEventCallback.default)(refSetter('scrollbarHorizontal'));
|
|
451
525
|
const getters = {
|
|
452
526
|
setPanels,
|
|
453
527
|
getOffsetTop,
|
|
454
528
|
getRows,
|
|
529
|
+
rows: params.rows,
|
|
455
530
|
getContainerProps: () => ({
|
|
456
|
-
ref:
|
|
531
|
+
ref: containerRef
|
|
457
532
|
}),
|
|
458
533
|
getScrollerProps: () => ({
|
|
459
|
-
ref:
|
|
460
|
-
onScroll: handleScroll,
|
|
461
|
-
onWheel,
|
|
462
|
-
onTouchMove,
|
|
534
|
+
ref: scrollerRef,
|
|
463
535
|
style: scrollerStyle,
|
|
464
536
|
role: 'presentation',
|
|
465
537
|
// `tabIndex` shouldn't be used along role=presentation, but it fixes a Firefox bug
|
|
@@ -472,28 +544,17 @@ function useVirtualization(store, params, api) {
|
|
|
472
544
|
role: 'presentation'
|
|
473
545
|
}),
|
|
474
546
|
getScrollbarVerticalProps: () => ({
|
|
475
|
-
ref:
|
|
547
|
+
ref: scrollbarVerticalRef,
|
|
476
548
|
scrollPosition
|
|
477
549
|
}),
|
|
478
550
|
getScrollbarHorizontalProps: () => ({
|
|
479
|
-
ref:
|
|
551
|
+
ref: scrollbarHorizontalRef,
|
|
480
552
|
scrollPosition
|
|
481
553
|
}),
|
|
482
554
|
getScrollAreaProps: () => ({
|
|
483
555
|
scrollPosition
|
|
484
556
|
})
|
|
485
557
|
};
|
|
486
|
-
(0, _useFirstRender.useFirstRender)(() => {
|
|
487
|
-
store.state = (0, _extends2.default)({}, store.state, {
|
|
488
|
-
getters
|
|
489
|
-
});
|
|
490
|
-
});
|
|
491
|
-
React.useEffect(() => {
|
|
492
|
-
store.update({
|
|
493
|
-
getters
|
|
494
|
-
});
|
|
495
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
496
|
-
}, Object.values(getters));
|
|
497
558
|
|
|
498
559
|
/* Placeholder API functions for colspan & rowspan to re-implement */
|
|
499
560
|
|
|
@@ -511,6 +572,7 @@ function useVirtualization(store, params, api) {
|
|
|
511
572
|
useVirtualization: () => (0, _store.useStore)(store, state => state),
|
|
512
573
|
setPanels,
|
|
513
574
|
forceUpdateRenderContext,
|
|
575
|
+
scheduleUpdateRenderContext,
|
|
514
576
|
getCellColSpanInfo,
|
|
515
577
|
calculateColSpan,
|
|
516
578
|
getHiddenCellsOrigin
|
|
@@ -586,7 +648,6 @@ function computeRenderContext(inputs, scrollPosition, scrollCache) {
|
|
|
586
648
|
// lastColumnIndex: 1,
|
|
587
649
|
// };
|
|
588
650
|
// }
|
|
589
|
-
|
|
590
651
|
if (inputs.enabledForColumns) {
|
|
591
652
|
let firstColumnIndex = 0;
|
|
592
653
|
let lastColumnIndex = inputs.columnPositions.length;
|
package/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mui/x-virtualizer",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.10",
|
|
4
4
|
"author": "MUI Team",
|
|
5
5
|
"description": "MUI virtualization library",
|
|
6
6
|
"license": "MIT",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@babel/runtime": "^7.28.4",
|
|
31
31
|
"@mui/utils": "^7.3.5",
|
|
32
|
-
"@mui/x-internals": "8.
|
|
32
|
+
"@mui/x-internals": "8.19.0"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|
|
35
35
|
"react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
package/useVirtualizer.d.ts
CHANGED
|
@@ -99,8 +99,8 @@ export type VirtualizerParams = {
|
|
|
99
99
|
export declare const useVirtualizer: (params: VirtualizerParams) => {
|
|
100
100
|
store: Store<Dimensions.State & Virtualization.State & Colspan.State & Rowspan.State>;
|
|
101
101
|
api: {
|
|
102
|
-
updateDimensions: () => void;
|
|
103
|
-
debouncedUpdateDimensions: ((() => void) & import("@mui/x-internals/throttle").Cancelable) | undefined;
|
|
102
|
+
updateDimensions: (firstUpdate?: boolean) => void;
|
|
103
|
+
debouncedUpdateDimensions: (((firstUpdate?: boolean) => void) & import("@mui/x-internals/throttle").Cancelable) | undefined;
|
|
104
104
|
rowsMeta: {
|
|
105
105
|
getRowHeight: (rowId: import("./models/index.js").RowId) => any;
|
|
106
106
|
setLastMeasuredRowIndex: (index: number) => void;
|
|
@@ -121,14 +121,12 @@ export declare const useVirtualizer: (params: VirtualizerParams) => {
|
|
|
121
121
|
position?: import("./models/index.js").PinnedRowPosition;
|
|
122
122
|
renderContext?: RenderContext;
|
|
123
123
|
}, unstable_rowTree?: Record<import("./models/index.js").RowId, any>) => React.ReactNode[];
|
|
124
|
+
rows: RowEntry[];
|
|
124
125
|
getContainerProps: () => {
|
|
125
|
-
ref: (node: HTMLDivElement | null) => void;
|
|
126
|
+
ref: (node: HTMLDivElement | null) => (() => void | undefined) | undefined;
|
|
126
127
|
};
|
|
127
128
|
getScrollerProps: () => {
|
|
128
|
-
ref: (node: HTMLDivElement | null) => void;
|
|
129
|
-
onScroll: () => void;
|
|
130
|
-
onWheel: ((event: React.WheelEvent) => void) | undefined;
|
|
131
|
-
onTouchMove: ((event: React.TouchEvent) => void) | undefined;
|
|
129
|
+
ref: (node: HTMLDivElement | null) => (() => void | undefined) | undefined;
|
|
132
130
|
style: React.CSSProperties;
|
|
133
131
|
role: string;
|
|
134
132
|
tabIndex: number | undefined;
|
|
@@ -162,6 +160,7 @@ export declare const useVirtualizer: (params: VirtualizerParams) => {
|
|
|
162
160
|
useVirtualization: () => BaseState;
|
|
163
161
|
setPanels: React.Dispatch<React.SetStateAction<Readonly<Map<any, React.ReactNode>>>>;
|
|
164
162
|
forceUpdateRenderContext: () => void;
|
|
163
|
+
scheduleUpdateRenderContext: () => void;
|
|
165
164
|
getCellColSpanInfo: (rowId: import("./models/index.js").RowId, columnIndex: integer) => import("./models/index.js").CellColSpanInfo;
|
|
166
165
|
calculateColSpan: (rowId: import("./models/index.js").RowId, minFirstColumn: integer, maxLastColumn: integer, columns: ColumnWithWidth[]) => void;
|
|
167
166
|
getHiddenCellsOrigin: () => Record<import("./models/index.js").RowId, Record<number, number>>;
|