@mui/x-virtualizer 0.1.0 → 0.1.2
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 +217 -6
- package/esm/features/colspan.d.ts +4 -0
- package/esm/features/colspan.js +4 -3
- package/esm/features/dimensions.d.ts +10 -0
- package/esm/features/dimensions.js +30 -49
- package/esm/features/virtualization.d.ts +17 -10
- package/esm/features/virtualization.js +55 -74
- package/esm/index.js +1 -1
- package/esm/models/core.d.ts +10 -4
- package/esm/models/core.js +20 -8
- package/esm/models/dimensions.d.ts +2 -33
- package/esm/useVirtualizer.d.ts +34 -53
- package/features/colspan.d.ts +4 -0
- package/features/colspan.js +4 -3
- package/features/dimensions.d.ts +10 -0
- package/features/dimensions.js +28 -48
- package/features/virtualization.d.ts +17 -10
- package/features/virtualization.js +55 -74
- package/index.js +1 -1
- package/models/core.d.ts +10 -4
- package/models/core.js +21 -9
- package/models/dimensions.d.ts +2 -33
- package/package.json +26 -15
- package/useVirtualizer.d.ts +34 -53
|
@@ -11,6 +11,7 @@ import * as platform from '@mui/x-internals/platform';
|
|
|
11
11
|
import { useRunOnce } from '@mui/x-internals/useRunOnce';
|
|
12
12
|
import { useFirstRender } from '@mui/x-internals/useFirstRender';
|
|
13
13
|
import { createSelector, useStore, useStoreEffect } from '@mui/x-internals/store';
|
|
14
|
+
import { PinnedRows, PinnedColumns } from "../models/core.js";
|
|
14
15
|
import { Dimensions } from "./dimensions.js";
|
|
15
16
|
import { ScrollDirection } from "../models/index.js";
|
|
16
17
|
|
|
@@ -57,28 +58,29 @@ function initializeState(params) {
|
|
|
57
58
|
|
|
58
59
|
function useVirtualization(store, params, api) {
|
|
59
60
|
const {
|
|
60
|
-
initialState,
|
|
61
|
-
isRtl,
|
|
62
|
-
rows,
|
|
63
|
-
range,
|
|
64
|
-
columns,
|
|
65
|
-
pinnedRows,
|
|
66
|
-
pinnedColumns,
|
|
67
61
|
refs,
|
|
68
|
-
hasColSpan,
|
|
69
62
|
dimensions: {
|
|
70
63
|
rowHeight,
|
|
71
64
|
columnsTotalWidth
|
|
72
65
|
},
|
|
73
|
-
|
|
66
|
+
virtualization: {
|
|
67
|
+
isRtl = false,
|
|
68
|
+
rowBufferPx = 150,
|
|
69
|
+
columnBufferPx = 150
|
|
70
|
+
},
|
|
71
|
+
colspan,
|
|
72
|
+
initialState,
|
|
73
|
+
rows,
|
|
74
|
+
range,
|
|
75
|
+
columns,
|
|
76
|
+
pinnedRows = PinnedRows.EMPTY,
|
|
77
|
+
pinnedColumns = PinnedColumns.EMPTY,
|
|
74
78
|
minimalContentHeight,
|
|
75
79
|
autoHeight,
|
|
76
80
|
onWheel,
|
|
77
81
|
onTouchMove,
|
|
78
82
|
onRenderContextChange,
|
|
79
83
|
onScrollChange,
|
|
80
|
-
rowBufferPx,
|
|
81
|
-
columnBufferPx,
|
|
82
84
|
scrollReset,
|
|
83
85
|
renderRow,
|
|
84
86
|
renderInfiniteLoadingTrigger
|
|
@@ -86,10 +88,12 @@ function useVirtualization(store, params, api) {
|
|
|
86
88
|
const needsHorizontalScrollbar = useStore(store, Dimensions.selectors.needsHorizontalScrollbar);
|
|
87
89
|
const hasBottomPinnedRows = pinnedRows.bottom.length > 0;
|
|
88
90
|
const [panels, setPanels] = React.useState(EMPTY_DETAIL_PANELS);
|
|
91
|
+
const [, setRefTick] = React.useState(0);
|
|
89
92
|
const isRenderContextReady = React.useRef(false);
|
|
90
93
|
const renderContext = useStore(store, selectors.renderContext);
|
|
91
94
|
const enabledForRows = useStore(store, selectors.enabledForRows);
|
|
92
95
|
const enabledForColumns = useStore(store, selectors.enabledForColumns);
|
|
96
|
+
const contentHeight = useStore(store, Dimensions.selectors.contentHeight);
|
|
93
97
|
|
|
94
98
|
/*
|
|
95
99
|
* Scroll context logic
|
|
@@ -114,18 +118,17 @@ function useVirtualization(store, params, api) {
|
|
|
114
118
|
const frozenContext = React.useRef(undefined);
|
|
115
119
|
const scrollCache = useLazyRef(() => createScrollCache(isRtl, rowBufferPx, columnBufferPx, rowHeight * 15, MINIMUM_COLUMN_WIDTH * 6)).current;
|
|
116
120
|
const updateRenderContext = React.useCallback(nextRenderContext => {
|
|
117
|
-
if (areRenderContextsEqual(nextRenderContext, store.state.virtualization.renderContext)) {
|
|
118
|
-
|
|
121
|
+
if (!areRenderContextsEqual(nextRenderContext, store.state.virtualization.renderContext)) {
|
|
122
|
+
store.set('virtualization', _extends({}, store.state.virtualization, {
|
|
123
|
+
renderContext: nextRenderContext
|
|
124
|
+
}));
|
|
119
125
|
}
|
|
120
|
-
const didRowsIntervalChange = nextRenderContext.firstRowIndex !== previousRowContext.current.firstRowIndex || nextRenderContext.lastRowIndex !== previousRowContext.current.lastRowIndex;
|
|
121
|
-
store.set('virtualization', _extends({}, store.state.virtualization, {
|
|
122
|
-
renderContext: nextRenderContext
|
|
123
|
-
}));
|
|
124
126
|
|
|
125
127
|
// The lazy-loading hook is listening to `renderedRowsIntervalChange`,
|
|
126
128
|
// but only does something if we already have a render context, because
|
|
127
129
|
// otherwise we would call an update directly on mount
|
|
128
130
|
const isReady = Dimensions.selectors.dimensions(store.state).isReady;
|
|
131
|
+
const didRowsIntervalChange = nextRenderContext.firstRowIndex !== previousRowContext.current.firstRowIndex || nextRenderContext.lastRowIndex !== previousRowContext.current.lastRowIndex;
|
|
129
132
|
if (isReady && didRowsIntervalChange) {
|
|
130
133
|
previousRowContext.current = nextRenderContext;
|
|
131
134
|
onRenderContextChange?.(nextRenderContext);
|
|
@@ -150,7 +153,7 @@ function useVirtualization(store, params, api) {
|
|
|
150
153
|
const dy = newScroll.top - scrollPosition.current.top;
|
|
151
154
|
const isScrolling = dx !== 0 || dy !== 0;
|
|
152
155
|
scrollPosition.current = newScroll;
|
|
153
|
-
const direction = isScrolling ?
|
|
156
|
+
const direction = isScrolling ? ScrollDirection.forDelta(dx, dy) : ScrollDirection.NONE;
|
|
154
157
|
|
|
155
158
|
// Since previous render, we have scrolled...
|
|
156
159
|
const rowScroll = Math.abs(scrollPosition.current.top - previousContextScrollPosition.current.top);
|
|
@@ -218,9 +221,7 @@ function useVirtualization(store, params, api) {
|
|
|
218
221
|
* section of code to the DataGrid's rowTree model. The `unstable_rowTree` param is a temporary
|
|
219
222
|
* solution to decouple the code.
|
|
220
223
|
*/
|
|
221
|
-
const getRows = (
|
|
222
|
-
// eslint-disable-next-line @typescript-eslint/default-param-last
|
|
223
|
-
rowParams = {}, unstable_rowTree) => {
|
|
224
|
+
const getRows = (rowParams = {}, unstable_rowTree) => {
|
|
224
225
|
if (!rowParams.rows && !range) {
|
|
225
226
|
return [];
|
|
226
227
|
}
|
|
@@ -250,7 +251,7 @@ function useVirtualization(store, params, api) {
|
|
|
250
251
|
const lastRowToRender = Math.min(baseRenderContext.lastRowIndex, rowModels.length);
|
|
251
252
|
const rowIndexes = rowParams.rows ? createRange(0, rowParams.rows.length) : createRange(firstRowToRender, lastRowToRender);
|
|
252
253
|
let virtualRowIndex = -1;
|
|
253
|
-
const focusedVirtualCell = params.focusedVirtualCell();
|
|
254
|
+
const focusedVirtualCell = params.focusedVirtualCell?.();
|
|
254
255
|
if (!isPinnedSection && focusedVirtualCell) {
|
|
255
256
|
if (focusedVirtualCell.rowIndex < firstRowToRender) {
|
|
256
257
|
rowIndexes.unshift(focusedVirtualCell.rowIndex);
|
|
@@ -275,13 +276,13 @@ function useVirtualization(store, params, api) {
|
|
|
275
276
|
// See:
|
|
276
277
|
// - https://github.com/mui/mui-x/issues/16638
|
|
277
278
|
// - https://github.com/mui/mui-x/issues/17022
|
|
278
|
-
if (!unstable_rowTree[id]) {
|
|
279
|
+
if (unstable_rowTree && !unstable_rowTree[id]) {
|
|
279
280
|
return;
|
|
280
281
|
}
|
|
281
282
|
const rowIndex = (range?.firstRowIndex || 0) + rowIndexOffset + rowIndexInPage;
|
|
282
283
|
|
|
283
284
|
// NOTE: This is an expensive feature, the colSpan code could be optimized.
|
|
284
|
-
if (
|
|
285
|
+
if (colspan?.enabled) {
|
|
285
286
|
const minFirstColumn = pinnedColumns.left.length;
|
|
286
287
|
const maxLastColumn = columns.length - pinnedColumns.right.length;
|
|
287
288
|
api.calculateColSpan(id, minFirstColumn, maxLastColumn, columns);
|
|
@@ -327,7 +328,6 @@ function useVirtualization(store, params, api) {
|
|
|
327
328
|
offsetLeft,
|
|
328
329
|
columnsTotalWidth,
|
|
329
330
|
baseRowHeight,
|
|
330
|
-
columns,
|
|
331
331
|
firstColumnIndex,
|
|
332
332
|
lastColumnIndex,
|
|
333
333
|
focusedColumnIndex: isVirtualFocusColumn ? focusedVirtualCell.columnIndex : undefined,
|
|
@@ -364,12 +364,12 @@ function useVirtualization(store, params, api) {
|
|
|
364
364
|
}
|
|
365
365
|
return size;
|
|
366
366
|
}, [columnsTotalWidth, contentHeight, needsHorizontalScrollbar, minimalContentHeight]);
|
|
367
|
-
const
|
|
368
|
-
const
|
|
367
|
+
const scrollRestoreCallback = React.useRef(null);
|
|
368
|
+
const contentNodeRef = React.useCallback(node => {
|
|
369
369
|
if (!node) {
|
|
370
370
|
return;
|
|
371
371
|
}
|
|
372
|
-
|
|
372
|
+
scrollRestoreCallback.current?.(columnsTotalWidth, contentHeight);
|
|
373
373
|
}, [columnsTotalWidth, contentHeight]);
|
|
374
374
|
useEnhancedEffect(() => {
|
|
375
375
|
if (!isRenderContextReady.current) {
|
|
@@ -391,54 +391,58 @@ function useVirtualization(store, params, api) {
|
|
|
391
391
|
top,
|
|
392
392
|
left
|
|
393
393
|
} = initialState.scroll;
|
|
394
|
-
|
|
395
|
-
// On initial mount, if we have columns available, we can restore the horizontal scroll immediately, but we need to skip the resulting scroll event, otherwise we would recalculate the render context at position top=0, left=restoredValue, but the initial render context is already calculated based on the initial value of scrollPosition ref.
|
|
396
394
|
const isScrollRestored = {
|
|
397
395
|
top: !(top > 0),
|
|
398
396
|
left: !(left > 0)
|
|
399
397
|
};
|
|
400
398
|
if (!isScrollRestored.left && columnsTotalWidth) {
|
|
401
399
|
scroller.scrollLeft = left;
|
|
402
|
-
ignoreNextScrollEvent.current = true;
|
|
403
400
|
isScrollRestored.left = true;
|
|
401
|
+
ignoreNextScrollEvent.current = true;
|
|
404
402
|
}
|
|
405
403
|
|
|
406
|
-
//
|
|
404
|
+
// To restore the vertical scroll, we need to wait until the rows are available in the DOM (otherwise
|
|
405
|
+
// there's nowhere to scroll). We still set the scrollTop to the initial value at this point in case
|
|
406
|
+
// there already are rows rendered in the DOM, but we only confirm `isScrollRestored.top = true` in the
|
|
407
|
+
// asynchronous callback below.
|
|
407
408
|
if (!isScrollRestored.top && contentHeight) {
|
|
408
409
|
scroller.scrollTop = top;
|
|
409
410
|
ignoreNextScrollEvent.current = true;
|
|
410
|
-
isScrollRestored.top = true;
|
|
411
411
|
}
|
|
412
|
-
|
|
413
|
-
// To restore the vertical scroll, we need to wait until the rows are available in the DOM (otherwise there's nowhere to scroll), but before paint to avoid reflows
|
|
414
412
|
if (!isScrollRestored.top || !isScrollRestored.left) {
|
|
415
|
-
|
|
413
|
+
scrollRestoreCallback.current = (columnsTotalWidthCurrent, contentHeightCurrent) => {
|
|
416
414
|
if (!isScrollRestored.left && columnsTotalWidthCurrent) {
|
|
417
415
|
scroller.scrollLeft = left;
|
|
418
|
-
ignoreNextScrollEvent.current = true;
|
|
419
416
|
isScrollRestored.left = true;
|
|
417
|
+
ignoreNextScrollEvent.current = true;
|
|
420
418
|
}
|
|
421
419
|
if (!isScrollRestored.top && contentHeightCurrent) {
|
|
422
420
|
scroller.scrollTop = top;
|
|
423
|
-
ignoreNextScrollEvent.current = true;
|
|
424
421
|
isScrollRestored.top = true;
|
|
422
|
+
ignoreNextScrollEvent.current = true;
|
|
425
423
|
}
|
|
426
424
|
if (isScrollRestored.left && isScrollRestored.top) {
|
|
427
|
-
|
|
425
|
+
scrollRestoreCallback.current = null;
|
|
428
426
|
}
|
|
429
427
|
};
|
|
430
428
|
}
|
|
431
429
|
}
|
|
432
430
|
});
|
|
433
431
|
useStoreEffect(store, Dimensions.selectors.dimensions, forceUpdateRenderContext);
|
|
432
|
+
const refSetter = name => node => {
|
|
433
|
+
if (node && refs[name].current !== node) {
|
|
434
|
+
refs[name].current = node;
|
|
435
|
+
setRefTick(tick => tick + 1);
|
|
436
|
+
}
|
|
437
|
+
};
|
|
434
438
|
const getters = {
|
|
435
439
|
setPanels,
|
|
436
440
|
getRows,
|
|
437
441
|
getContainerProps: () => ({
|
|
438
|
-
ref:
|
|
442
|
+
ref: refSetter('container')
|
|
439
443
|
}),
|
|
440
444
|
getScrollerProps: () => ({
|
|
441
|
-
ref:
|
|
445
|
+
ref: refSetter('scroller'),
|
|
442
446
|
onScroll: handleScroll,
|
|
443
447
|
onWheel,
|
|
444
448
|
onTouchMove,
|
|
@@ -449,19 +453,16 @@ function useVirtualization(store, params, api) {
|
|
|
449
453
|
tabIndex: platform.isFirefox ? -1 : undefined
|
|
450
454
|
}),
|
|
451
455
|
getContentProps: () => ({
|
|
456
|
+
ref: contentNodeRef,
|
|
452
457
|
style: contentSize,
|
|
453
|
-
role: 'presentation'
|
|
454
|
-
ref: onContentSizeApplied
|
|
455
|
-
}),
|
|
456
|
-
getRenderZoneProps: () => ({
|
|
457
|
-
role: 'rowgroup'
|
|
458
|
+
role: 'presentation'
|
|
458
459
|
}),
|
|
459
460
|
getScrollbarVerticalProps: () => ({
|
|
460
|
-
ref:
|
|
461
|
+
ref: refSetter('scrollbarVertical'),
|
|
461
462
|
scrollPosition
|
|
462
463
|
}),
|
|
463
464
|
getScrollbarHorizontalProps: () => ({
|
|
464
|
-
ref:
|
|
465
|
+
ref: refSetter('scrollbarHorizontal'),
|
|
465
466
|
scrollPosition
|
|
466
467
|
}),
|
|
467
468
|
getScrollAreaProps: () => ({
|
|
@@ -474,9 +475,9 @@ function useVirtualization(store, params, api) {
|
|
|
474
475
|
});
|
|
475
476
|
});
|
|
476
477
|
React.useEffect(() => {
|
|
477
|
-
store.update(
|
|
478
|
+
store.update({
|
|
478
479
|
getters
|
|
479
|
-
})
|
|
480
|
+
});
|
|
480
481
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
481
482
|
}, Object.values(getters));
|
|
482
483
|
|
|
@@ -514,8 +515,8 @@ function inputsSelector(store, params, api, enabledForRows, enabledForColumns) {
|
|
|
514
515
|
enabledForRows,
|
|
515
516
|
enabledForColumns,
|
|
516
517
|
autoHeight: params.autoHeight,
|
|
517
|
-
rowBufferPx: params.rowBufferPx,
|
|
518
|
-
columnBufferPx: params.columnBufferPx,
|
|
518
|
+
rowBufferPx: params.virtualization.rowBufferPx,
|
|
519
|
+
columnBufferPx: params.virtualization.columnBufferPx,
|
|
519
520
|
leftPinnedWidth: dimensions.leftPinnedWidth,
|
|
520
521
|
columnsTotalWidth: dimensions.columnsTotalWidth,
|
|
521
522
|
viewportInnerWidth: dimensions.viewportInnerSize.width,
|
|
@@ -645,8 +646,8 @@ function deriveRenderContext(inputs, nextRenderContext, scrollCache) {
|
|
|
645
646
|
const [initialFirstColumnToRender, lastColumnToRender] = getIndexesToRender({
|
|
646
647
|
firstIndex: nextRenderContext.firstColumnIndex,
|
|
647
648
|
lastIndex: nextRenderContext.lastColumnIndex,
|
|
648
|
-
minFirstIndex: inputs.pinnedColumns
|
|
649
|
-
maxLastIndex: inputs.columns.length - inputs.pinnedColumns
|
|
649
|
+
minFirstIndex: inputs.pinnedColumns?.left.length ?? 0,
|
|
650
|
+
maxLastIndex: inputs.columns.length - (inputs.pinnedColumns?.right.length ?? 0),
|
|
650
651
|
bufferBefore: scrollCache.buffer.columnBefore,
|
|
651
652
|
bufferAfter: scrollCache.buffer.columnAfter,
|
|
652
653
|
positions: inputs.columnPositions,
|
|
@@ -727,26 +728,6 @@ export function computeOffsetLeft(columnPositions, renderContext, pinnedLeftLeng
|
|
|
727
728
|
const left = (columnPositions[renderContext.firstColumnIndex] ?? 0) - (columnPositions[pinnedLeftLength] ?? 0);
|
|
728
729
|
return Math.abs(left);
|
|
729
730
|
}
|
|
730
|
-
function directionForDelta(dx, dy) {
|
|
731
|
-
if (dx === 0 && dy === 0) {
|
|
732
|
-
return ScrollDirection.NONE;
|
|
733
|
-
}
|
|
734
|
-
/* eslint-disable */
|
|
735
|
-
if (Math.abs(dy) >= Math.abs(dx)) {
|
|
736
|
-
if (dy > 0) {
|
|
737
|
-
return ScrollDirection.DOWN;
|
|
738
|
-
} else {
|
|
739
|
-
return ScrollDirection.UP;
|
|
740
|
-
}
|
|
741
|
-
} else {
|
|
742
|
-
if (dx > 0) {
|
|
743
|
-
return ScrollDirection.RIGHT;
|
|
744
|
-
} else {
|
|
745
|
-
return ScrollDirection.LEFT;
|
|
746
|
-
}
|
|
747
|
-
}
|
|
748
|
-
/* eslint-enable */
|
|
749
|
-
}
|
|
750
731
|
function bufferForDirection(isRtl, direction, rowBufferPx, columnBufferPx, verticalBuffer, horizontalBuffer) {
|
|
751
732
|
if (isRtl) {
|
|
752
733
|
switch (direction) {
|
package/esm/index.js
CHANGED
package/esm/models/core.d.ts
CHANGED
|
@@ -2,13 +2,13 @@ export type Size = {
|
|
|
2
2
|
width: number;
|
|
3
3
|
height: number;
|
|
4
4
|
};
|
|
5
|
-
export declare
|
|
6
|
-
|
|
5
|
+
export declare const Size: {
|
|
6
|
+
EMPTY: {
|
|
7
7
|
width: number;
|
|
8
8
|
height: number;
|
|
9
9
|
};
|
|
10
|
-
|
|
11
|
-
}
|
|
10
|
+
equals: (a: Size, b: Size) => boolean;
|
|
11
|
+
};
|
|
12
12
|
export type Row = {
|
|
13
13
|
[key: string | symbol]: any;
|
|
14
14
|
};
|
|
@@ -27,10 +27,16 @@ export type PinnedRows = {
|
|
|
27
27
|
top: RowEntry[];
|
|
28
28
|
bottom: RowEntry[];
|
|
29
29
|
};
|
|
30
|
+
export declare const PinnedRows: {
|
|
31
|
+
EMPTY: PinnedRows;
|
|
32
|
+
};
|
|
30
33
|
export type PinnedColumns = {
|
|
31
34
|
left: Column[];
|
|
32
35
|
right: Column[];
|
|
33
36
|
};
|
|
37
|
+
export declare const PinnedColumns: {
|
|
38
|
+
EMPTY: PinnedColumns;
|
|
39
|
+
};
|
|
34
40
|
export type FocusedCell = {
|
|
35
41
|
rowIndex: number;
|
|
36
42
|
columnIndex: number;
|
package/esm/models/core.js
CHANGED
|
@@ -1,15 +1,27 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-redeclare */
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
|
|
3
|
+
export const Size = {
|
|
4
|
+
EMPTY: {
|
|
5
5
|
width: 0,
|
|
6
6
|
height: 0
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
},
|
|
8
|
+
equals: (a, b) => a.width === b.width && a.height === b.height
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// TODO
|
|
12
|
+
|
|
13
|
+
export const PinnedRows = {
|
|
14
|
+
EMPTY: {
|
|
15
|
+
top: [],
|
|
16
|
+
bottom: []
|
|
10
17
|
}
|
|
11
|
-
|
|
12
|
-
|
|
18
|
+
};
|
|
19
|
+
export const PinnedColumns = {
|
|
20
|
+
EMPTY: {
|
|
21
|
+
left: [],
|
|
22
|
+
right: []
|
|
23
|
+
}
|
|
24
|
+
};
|
|
13
25
|
export let ScrollDirection = /*#__PURE__*/function (ScrollDirection) {
|
|
14
26
|
ScrollDirection[ScrollDirection["NONE"] = 0] = "NONE";
|
|
15
27
|
ScrollDirection[ScrollDirection["UP"] = 1] = "UP";
|
|
@@ -38,7 +38,7 @@ export interface DimensionsState {
|
|
|
38
38
|
*/
|
|
39
39
|
scrollbarSize: number;
|
|
40
40
|
/**
|
|
41
|
-
* Width of a row.
|
|
41
|
+
* Width of a row. At least as wide as `viewportOuterSize.width`.
|
|
42
42
|
*/
|
|
43
43
|
rowWidth: number;
|
|
44
44
|
/**
|
|
@@ -46,7 +46,7 @@ export interface DimensionsState {
|
|
|
46
46
|
*/
|
|
47
47
|
rowHeight: number;
|
|
48
48
|
/**
|
|
49
|
-
* Size of all the
|
|
49
|
+
* Size of all the columns.
|
|
50
50
|
*/
|
|
51
51
|
columnsTotalWidth: number;
|
|
52
52
|
/**
|
|
@@ -57,22 +57,6 @@ export interface DimensionsState {
|
|
|
57
57
|
* Size of right pinned columns.
|
|
58
58
|
*/
|
|
59
59
|
rightPinnedWidth: number;
|
|
60
|
-
/**
|
|
61
|
-
* Height of one column header.
|
|
62
|
-
*/
|
|
63
|
-
headerHeight: number;
|
|
64
|
-
/**
|
|
65
|
-
* Height of one column group header.
|
|
66
|
-
*/
|
|
67
|
-
groupHeaderHeight: number;
|
|
68
|
-
/**
|
|
69
|
-
* Height of header filters.
|
|
70
|
-
*/
|
|
71
|
-
headerFilterHeight: number;
|
|
72
|
-
/**
|
|
73
|
-
* Height of all the column headers.
|
|
74
|
-
*/
|
|
75
|
-
headersTotalHeight: number;
|
|
76
60
|
/**
|
|
77
61
|
* Size of the top container.
|
|
78
62
|
*/
|
|
@@ -103,21 +87,6 @@ export interface RowsMetaState {
|
|
|
103
87
|
*/
|
|
104
88
|
pinnedBottomRowsTotalHeight: number;
|
|
105
89
|
}
|
|
106
|
-
export interface RowVisibilityParams {
|
|
107
|
-
/**
|
|
108
|
-
* Whether this row is the first visible or not.
|
|
109
|
-
*/
|
|
110
|
-
isFirstVisible: boolean;
|
|
111
|
-
/**
|
|
112
|
-
* Whether this row is the last visible or not.
|
|
113
|
-
*/
|
|
114
|
-
isLastVisible: boolean;
|
|
115
|
-
/**
|
|
116
|
-
* Index of the row in the current page.
|
|
117
|
-
* If the pagination is disabled, it will be the index relative to all filtered rows.
|
|
118
|
-
*/
|
|
119
|
-
indexRelativeToCurrentPage: number;
|
|
120
|
-
}
|
|
121
90
|
export interface RowSpacing {
|
|
122
91
|
top?: number;
|
|
123
92
|
bottom?: number;
|
package/esm/useVirtualizer.d.ts
CHANGED
|
@@ -5,34 +5,32 @@ import { Colspan } from "./features/colspan.js";
|
|
|
5
5
|
import { Dimensions } from "./features/dimensions.js";
|
|
6
6
|
import { Rowspan } from "./features/rowspan.js";
|
|
7
7
|
import { Virtualization } from "./features/virtualization.js";
|
|
8
|
-
import type {
|
|
9
|
-
import type {
|
|
8
|
+
import type { HeightEntry, RowSpacing } from "./models/dimensions.js";
|
|
9
|
+
import type { ColspanParams } from "./features/colspan.js";
|
|
10
|
+
import type { DimensionsParams } from "./features/dimensions.js";
|
|
11
|
+
import type { VirtualizationParams } from "./features/virtualization.js";
|
|
10
12
|
import { ColumnWithWidth, FocusedCell, Size, PinnedRows, PinnedColumns, RenderContext, Row, RowEntry } from "./models/index.js";
|
|
11
13
|
export type Virtualizer = ReturnType<typeof useVirtualizer>;
|
|
12
14
|
export type VirtualScrollerCompat = Virtualization.State['getters'];
|
|
13
15
|
export type BaseState = Virtualization.State & Dimensions.State;
|
|
14
16
|
export type VirtualizerParams = {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
headerFilterHeight: number;
|
|
21
|
-
columnsTotalWidth: number;
|
|
22
|
-
headersTotalHeight: number;
|
|
23
|
-
leftPinnedWidth: number;
|
|
24
|
-
rightPinnedWidth: number;
|
|
17
|
+
refs: {
|
|
18
|
+
container: RefObject<HTMLDivElement | null>;
|
|
19
|
+
scroller: RefObject<HTMLDivElement | null>;
|
|
20
|
+
scrollbarVertical: RefObject<HTMLDivElement | null>;
|
|
21
|
+
scrollbarHorizontal: RefObject<HTMLDivElement | null>;
|
|
25
22
|
};
|
|
23
|
+
dimensions: DimensionsParams;
|
|
24
|
+
virtualization: VirtualizationParams;
|
|
25
|
+
colspan?: ColspanParams;
|
|
26
26
|
initialState?: {
|
|
27
27
|
scroll?: {
|
|
28
28
|
top: number;
|
|
29
29
|
left: number;
|
|
30
30
|
};
|
|
31
|
-
dimensions?: Partial<Dimensions.State['dimensions']>;
|
|
32
31
|
rowSpanning?: Rowspan.State['rowSpanning'];
|
|
33
32
|
virtualization?: Partial<Virtualization.State['virtualization']>;
|
|
34
33
|
};
|
|
35
|
-
isRtl: boolean;
|
|
36
34
|
/** current page rows */
|
|
37
35
|
rows: RowEntry[];
|
|
38
36
|
/** current page range */
|
|
@@ -40,21 +38,12 @@ export type VirtualizerParams = {
|
|
|
40
38
|
firstRowIndex: integer;
|
|
41
39
|
lastRowIndex: integer;
|
|
42
40
|
} | null;
|
|
43
|
-
rowIdToIndexMap: Map<RowId, number>;
|
|
44
41
|
rowCount: integer;
|
|
45
42
|
columns: ColumnWithWidth[];
|
|
46
|
-
pinnedRows
|
|
47
|
-
pinnedColumns
|
|
48
|
-
refs: {
|
|
49
|
-
container: RefObject<HTMLDivElement | null>;
|
|
50
|
-
scroller: RefObject<HTMLDivElement | null>;
|
|
51
|
-
scrollbarVertical: RefObject<HTMLDivElement | null>;
|
|
52
|
-
scrollbarHorizontal: RefObject<HTMLDivElement | null>;
|
|
53
|
-
};
|
|
54
|
-
hasColSpan: boolean;
|
|
55
|
-
contentHeight: number;
|
|
56
|
-
minimalContentHeight: number | string;
|
|
43
|
+
pinnedRows?: PinnedRows;
|
|
44
|
+
pinnedColumns?: PinnedColumns;
|
|
57
45
|
autoHeight: boolean;
|
|
46
|
+
minimalContentHeight?: number | string;
|
|
58
47
|
getRowHeight?: (row: RowEntry) => number | null | undefined | 'auto';
|
|
59
48
|
/**
|
|
60
49
|
* Function that returns the estimated height for a row.
|
|
@@ -67,10 +56,9 @@ export type VirtualizerParams = {
|
|
|
67
56
|
/**
|
|
68
57
|
* Function that allows to specify the spacing between rows.
|
|
69
58
|
* @param rowEntry
|
|
70
|
-
* @param visibility With all properties from [[RowVisibilityParams]].
|
|
71
59
|
* @returns The row spacing values.
|
|
72
60
|
*/
|
|
73
|
-
getRowSpacing?: (rowEntry: RowEntry
|
|
61
|
+
getRowSpacing?: (rowEntry: RowEntry) => RowSpacing;
|
|
74
62
|
/** Update the row height values before they're used.
|
|
75
63
|
* Used to add detail panel heights.
|
|
76
64
|
* @param entry
|
|
@@ -87,11 +75,8 @@ export type VirtualizerParams = {
|
|
|
87
75
|
top: number;
|
|
88
76
|
left: number;
|
|
89
77
|
}, nextRenderContext: RenderContext) => void;
|
|
90
|
-
focusedVirtualCell
|
|
91
|
-
rowBufferPx: number;
|
|
92
|
-
columnBufferPx: number;
|
|
78
|
+
focusedVirtualCell?: () => FocusedCell | null;
|
|
93
79
|
scrollReset?: any;
|
|
94
|
-
getColspan: (rowId: RowId, column: ColumnWithWidth, columnIndex: integer) => number;
|
|
95
80
|
renderRow: (params: {
|
|
96
81
|
id: any;
|
|
97
82
|
model: Row;
|
|
@@ -99,7 +84,6 @@ export type VirtualizerParams = {
|
|
|
99
84
|
offsetLeft: number;
|
|
100
85
|
columnsTotalWidth: number;
|
|
101
86
|
baseRowHeight: number | 'auto';
|
|
102
|
-
columns: ColumnWithWidth[];
|
|
103
87
|
firstColumnIndex: number;
|
|
104
88
|
lastColumnIndex: number;
|
|
105
89
|
focusedColumnIndex: number | undefined;
|
|
@@ -116,29 +100,29 @@ export declare const useVirtualizer: (params: VirtualizerParams) => {
|
|
|
116
100
|
updateDimensions: () => void;
|
|
117
101
|
debouncedUpdateDimensions: ((() => void) & import("@mui/x-internals/throttle/throttle").Cancelable) | undefined;
|
|
118
102
|
rowsMeta: {
|
|
119
|
-
getRowHeight: (rowId: RowId) => any;
|
|
103
|
+
getRowHeight: (rowId: import("./models/index.js").RowId) => any;
|
|
120
104
|
setLastMeasuredRowIndex: (index: number) => void;
|
|
121
|
-
storeRowHeightMeasurement: (id: RowId, height: number) => void;
|
|
105
|
+
storeRowHeightMeasurement: (id: import("./models/index.js").RowId, height: number) => void;
|
|
122
106
|
hydrateRowsMeta: () => void;
|
|
123
|
-
observeRowHeight: (element: Element, rowId: RowId) => () => void | undefined;
|
|
124
|
-
rowHasAutoHeight: (id: RowId) => any;
|
|
125
|
-
getRowHeightEntry: (rowId: RowId) => any;
|
|
107
|
+
observeRowHeight: (element: Element, rowId: import("./models/index.js").RowId) => () => void | undefined;
|
|
108
|
+
rowHasAutoHeight: (id: import("./models/index.js").RowId) => any;
|
|
109
|
+
getRowHeightEntry: (rowId: import("./models/index.js").RowId) => any;
|
|
126
110
|
getLastMeasuredRowIndex: () => number;
|
|
127
111
|
resetRowHeights: () => void;
|
|
128
112
|
};
|
|
129
113
|
} & {
|
|
130
114
|
getters: {
|
|
131
115
|
setPanels: React.Dispatch<React.SetStateAction<Readonly<Map<any, React.ReactNode>>>>;
|
|
132
|
-
getRows: (rowParams
|
|
116
|
+
getRows: (rowParams?: {
|
|
133
117
|
rows?: RowEntry[];
|
|
134
118
|
position?: import("./models/index.js").PinnedRowPosition;
|
|
135
119
|
renderContext?: RenderContext;
|
|
136
|
-
}
|
|
120
|
+
}, unstable_rowTree?: Record<import("./models/index.js").RowId, any>) => React.ReactNode[];
|
|
137
121
|
getContainerProps: () => {
|
|
138
|
-
ref:
|
|
122
|
+
ref: (node: HTMLDivElement | null) => void;
|
|
139
123
|
};
|
|
140
124
|
getScrollerProps: () => {
|
|
141
|
-
ref:
|
|
125
|
+
ref: (node: HTMLDivElement | null) => void;
|
|
142
126
|
onScroll: () => void;
|
|
143
127
|
onWheel: ((event: React.WheelEvent) => void) | undefined;
|
|
144
128
|
onTouchMove: ((event: React.TouchEvent) => void) | undefined;
|
|
@@ -147,22 +131,19 @@ export declare const useVirtualizer: (params: VirtualizerParams) => {
|
|
|
147
131
|
tabIndex: number | undefined;
|
|
148
132
|
};
|
|
149
133
|
getContentProps: () => {
|
|
150
|
-
style: React.CSSProperties;
|
|
151
|
-
role: string;
|
|
152
134
|
ref: (node: HTMLDivElement | null) => void;
|
|
153
|
-
|
|
154
|
-
getRenderZoneProps: () => {
|
|
135
|
+
style: React.CSSProperties;
|
|
155
136
|
role: string;
|
|
156
137
|
};
|
|
157
138
|
getScrollbarVerticalProps: () => {
|
|
158
|
-
ref:
|
|
139
|
+
ref: (node: HTMLDivElement | null) => void;
|
|
159
140
|
scrollPosition: React.RefObject<{
|
|
160
141
|
top: number;
|
|
161
142
|
left: number;
|
|
162
143
|
}>;
|
|
163
144
|
};
|
|
164
145
|
getScrollbarHorizontalProps: () => {
|
|
165
|
-
ref:
|
|
146
|
+
ref: (node: HTMLDivElement | null) => void;
|
|
166
147
|
scrollPosition: React.RefObject<{
|
|
167
148
|
top: number;
|
|
168
149
|
left: number;
|
|
@@ -178,13 +159,13 @@ export declare const useVirtualizer: (params: VirtualizerParams) => {
|
|
|
178
159
|
useVirtualization: () => BaseState;
|
|
179
160
|
setPanels: React.Dispatch<React.SetStateAction<Readonly<Map<any, React.ReactNode>>>>;
|
|
180
161
|
forceUpdateRenderContext: () => void;
|
|
181
|
-
getCellColSpanInfo: (rowId: RowId, columnIndex: integer) => import("./models/index.js").CellColSpanInfo;
|
|
182
|
-
calculateColSpan: (rowId: RowId, minFirstColumn: integer, maxLastColumn: integer, columns: ColumnWithWidth[]) => void;
|
|
183
|
-
getHiddenCellsOrigin: () => Record<RowId, Record<number, number>>;
|
|
162
|
+
getCellColSpanInfo: (rowId: import("./models/index.js").RowId, columnIndex: integer) => import("./models/index.js").CellColSpanInfo;
|
|
163
|
+
calculateColSpan: (rowId: import("./models/index.js").RowId, minFirstColumn: integer, maxLastColumn: integer, columns: ColumnWithWidth[]) => void;
|
|
164
|
+
getHiddenCellsOrigin: () => Record<import("./models/index.js").RowId, Record<number, number>>;
|
|
184
165
|
} & {
|
|
185
166
|
resetColSpan: () => void;
|
|
186
|
-
getCellColSpanInfo: (rowId: RowId, columnIndex: integer) => import("./models/index.js").CellColSpanInfo | undefined;
|
|
187
|
-
calculateColSpan: (rowId: RowId, minFirstColumn: integer, maxLastColumn: integer, columns: ColumnWithWidth[]) => void;
|
|
167
|
+
getCellColSpanInfo: (rowId: import("./models/index.js").RowId, columnIndex: integer) => import("./models/index.js").CellColSpanInfo | undefined;
|
|
168
|
+
calculateColSpan: (rowId: import("./models/index.js").RowId, minFirstColumn: integer, maxLastColumn: integer, columns: ColumnWithWidth[]) => void;
|
|
188
169
|
} & {
|
|
189
170
|
getHiddenCellsOrigin: () => Record<number, Record<number, number>>;
|
|
190
171
|
} & {
|
package/features/colspan.d.ts
CHANGED
|
@@ -6,6 +6,10 @@ import type { CellColSpanInfo } from "../models/colspan.js";
|
|
|
6
6
|
import { Virtualization } from "./virtualization.js";
|
|
7
7
|
type ColumnIndex = number;
|
|
8
8
|
type ColspanMap = Map<RowId, Record<ColumnIndex, CellColSpanInfo>>;
|
|
9
|
+
export type ColspanParams = {
|
|
10
|
+
enabled: boolean;
|
|
11
|
+
getColspan: (rowId: RowId, column: ColumnWithWidth, columnIndex: integer) => integer;
|
|
12
|
+
};
|
|
9
13
|
export declare const Colspan: {
|
|
10
14
|
initialize: typeof initializeState;
|
|
11
15
|
use: typeof useColspan;
|
package/features/colspan.js
CHANGED
|
@@ -20,6 +20,7 @@ function initializeState(_params) {
|
|
|
20
20
|
};
|
|
21
21
|
}
|
|
22
22
|
function useColspan(store, params, api) {
|
|
23
|
+
const getColspan = params.colspan?.getColspan;
|
|
23
24
|
const resetColSpan = () => {
|
|
24
25
|
store.state.colspanMap = new Map();
|
|
25
26
|
};
|
|
@@ -28,14 +29,14 @@ function useColspan(store, params, api) {
|
|
|
28
29
|
};
|
|
29
30
|
|
|
30
31
|
// Calculate `colSpan` for each cell in the row
|
|
31
|
-
const calculateColSpan = (0, _useEventCallback.default)((rowId, minFirstColumn, maxLastColumn, columns) => {
|
|
32
|
+
const calculateColSpan = (0, _useEventCallback.default)(getColspan ? (rowId, minFirstColumn, maxLastColumn, columns) => {
|
|
32
33
|
for (let i = minFirstColumn; i < maxLastColumn; i += 1) {
|
|
33
|
-
const cellProps = calculateCellColSpan(store.state.colspanMap, i, rowId, minFirstColumn, maxLastColumn, columns,
|
|
34
|
+
const cellProps = calculateCellColSpan(store.state.colspanMap, i, rowId, minFirstColumn, maxLastColumn, columns, getColspan);
|
|
34
35
|
if (cellProps.colSpan > 1) {
|
|
35
36
|
i += cellProps.colSpan - 1;
|
|
36
37
|
}
|
|
37
38
|
}
|
|
38
|
-
});
|
|
39
|
+
} : () => {});
|
|
39
40
|
api.calculateColSpan = calculateColSpan;
|
|
40
41
|
return {
|
|
41
42
|
resetColSpan,
|