@mui/x-virtualizer 0.2.10 → 0.2.12
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 +248 -0
- package/constants.d.ts +22 -0
- package/constants.js +26 -0
- package/esm/constants.d.ts +22 -0
- package/esm/constants.js +20 -0
- package/esm/features/colspan.d.ts +4 -4
- package/esm/features/dimensions.d.ts +14 -8
- package/esm/features/dimensions.js +26 -7
- package/esm/features/index.d.ts +1 -1
- package/esm/features/index.js +1 -1
- package/esm/features/keyboard.d.ts +3 -3
- package/esm/features/keyboard.js +1 -1
- package/esm/features/rowspan.d.ts +4 -4
- package/esm/features/virtualization/index.d.ts +2 -0
- package/esm/features/virtualization/index.js +2 -0
- package/esm/features/virtualization/layout.d.ts +129 -0
- package/esm/features/virtualization/layout.js +152 -0
- package/esm/features/{virtualization.d.ts → virtualization/virtualization.d.ts} +35 -58
- package/esm/features/{virtualization.js → virtualization/virtualization.js} +97 -134
- package/esm/index.d.ts +2 -1
- package/esm/index.js +3 -2
- package/esm/models/core.d.ts +7 -0
- package/esm/models/core.js +7 -0
- package/esm/models/dimensions.d.ts +8 -0
- package/esm/useVirtualizer.d.ts +25 -69
- package/esm/useVirtualizer.js +21 -4
- package/features/colspan.d.ts +4 -4
- package/features/dimensions.d.ts +14 -8
- package/features/dimensions.js +26 -7
- package/features/index.d.ts +1 -1
- package/features/keyboard.d.ts +3 -3
- package/features/rowspan.d.ts +4 -4
- package/features/virtualization/index.d.ts +2 -0
- package/features/virtualization/index.js +27 -0
- package/features/virtualization/layout.d.ts +129 -0
- package/features/virtualization/layout.js +163 -0
- package/features/{virtualization.d.ts → virtualization/virtualization.d.ts} +35 -58
- package/features/{virtualization.js → virtualization/virtualization.js} +97 -134
- package/index.d.ts +2 -1
- package/index.js +12 -1
- package/models/core.d.ts +7 -0
- package/models/core.js +8 -1
- package/models/dimensions.d.ts +8 -0
- package/package.json +2 -2
- package/useVirtualizer.d.ts +25 -69
- package/useVirtualizer.js +20 -3
|
@@ -11,9 +11,9 @@ import * as platform from '@mui/x-internals/platform';
|
|
|
11
11
|
import { useRunOnce } from '@mui/x-internals/useRunOnce';
|
|
12
12
|
import { createSelector, useStore, useStoreEffect } from '@mui/x-internals/store';
|
|
13
13
|
import reactMajor from '@mui/x-internals/reactMajor';
|
|
14
|
-
import { PinnedRows, PinnedColumns } from "
|
|
15
|
-
import { Dimensions, observeRootNode } from "
|
|
16
|
-
import { ScrollDirection } from "
|
|
14
|
+
import { PinnedRows, PinnedColumns } from "../../models/core.js";
|
|
15
|
+
import { Dimensions, observeRootNode } from "../dimensions.js";
|
|
16
|
+
import { ScrollPosition, ScrollDirection } from "../../models/index.js";
|
|
17
17
|
|
|
18
18
|
/* eslint-disable import/export, @typescript-eslint/no-redeclare */
|
|
19
19
|
|
|
@@ -30,12 +30,18 @@ export const EMPTY_RENDER_CONTEXT = {
|
|
|
30
30
|
firstColumnIndex: 0,
|
|
31
31
|
lastColumnIndex: 0
|
|
32
32
|
};
|
|
33
|
-
const selectors = {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
const selectors = (() => {
|
|
34
|
+
const firstRowIndexSelector = createSelector(state => state.virtualization.renderContext.firstRowIndex);
|
|
35
|
+
return {
|
|
36
|
+
store: createSelector(state => state.virtualization),
|
|
37
|
+
renderContext: createSelector(state => state.virtualization.renderContext),
|
|
38
|
+
enabledForRows: createSelector(state => state.virtualization.enabledForRows),
|
|
39
|
+
enabledForColumns: createSelector(state => state.virtualization.enabledForColumns),
|
|
40
|
+
offsetTop: createSelector(Dimensions.selectors.rowPositions, firstRowIndexSelector, (rowPositions, firstRowIndex) => rowPositions[firstRowIndex] ?? 0),
|
|
41
|
+
context: createSelector(state => state.virtualization.context),
|
|
42
|
+
scrollPosition: createSelector(state => state.virtualization.scrollPosition)
|
|
43
|
+
};
|
|
44
|
+
})();
|
|
39
45
|
export const Virtualization = {
|
|
40
46
|
initialize: initializeState,
|
|
41
47
|
use: useVirtualization,
|
|
@@ -47,7 +53,12 @@ function initializeState(params) {
|
|
|
47
53
|
enabled: !platform.isJSDOM,
|
|
48
54
|
enabledForRows: !platform.isJSDOM,
|
|
49
55
|
enabledForColumns: !platform.isJSDOM,
|
|
50
|
-
renderContext: EMPTY_RENDER_CONTEXT
|
|
56
|
+
renderContext: EMPTY_RENDER_CONTEXT,
|
|
57
|
+
props: params.layout.constructor.elements.reduce((acc, key) => (acc[key], acc), {}),
|
|
58
|
+
context: {},
|
|
59
|
+
scrollPosition: {
|
|
60
|
+
current: ScrollPosition.EMPTY
|
|
61
|
+
}
|
|
51
62
|
}, params.initialState?.virtualization),
|
|
52
63
|
// FIXME: refactor once the state shape is settled
|
|
53
64
|
getters: null
|
|
@@ -59,10 +70,10 @@ function initializeState(params) {
|
|
|
59
70
|
|
|
60
71
|
function useVirtualization(store, params, api) {
|
|
61
72
|
const {
|
|
62
|
-
|
|
73
|
+
layout,
|
|
63
74
|
dimensions: {
|
|
64
75
|
rowHeight,
|
|
65
|
-
columnsTotalWidth
|
|
76
|
+
columnsTotalWidth = 0
|
|
66
77
|
},
|
|
67
78
|
virtualization: {
|
|
68
79
|
isRtl = false,
|
|
@@ -76,8 +87,6 @@ function useVirtualization(store, params, api) {
|
|
|
76
87
|
columns,
|
|
77
88
|
pinnedRows = PinnedRows.EMPTY,
|
|
78
89
|
pinnedColumns = PinnedColumns.EMPTY,
|
|
79
|
-
minimalContentHeight,
|
|
80
|
-
autoHeight,
|
|
81
90
|
onWheel,
|
|
82
91
|
onTouchMove,
|
|
83
92
|
onRenderContextChange,
|
|
@@ -86,7 +95,6 @@ function useVirtualization(store, params, api) {
|
|
|
86
95
|
renderRow,
|
|
87
96
|
renderInfiniteLoadingTrigger
|
|
88
97
|
} = params;
|
|
89
|
-
const needsHorizontalScrollbar = useStore(store, Dimensions.selectors.needsHorizontalScrollbar);
|
|
90
98
|
const hasBottomPinnedRows = pinnedRows.bottom.length > 0;
|
|
91
99
|
const [panels, setPanels] = React.useState(EMPTY_DETAIL_PANELS);
|
|
92
100
|
const isUpdateScheduled = React.useRef(false);
|
|
@@ -94,7 +102,6 @@ function useVirtualization(store, params, api) {
|
|
|
94
102
|
const renderContext = useStore(store, selectors.renderContext);
|
|
95
103
|
const enabledForRows = useStore(store, selectors.enabledForRows);
|
|
96
104
|
const enabledForColumns = useStore(store, selectors.enabledForColumns);
|
|
97
|
-
const rowsMeta = useStore(store, Dimensions.selectors.rowsMeta);
|
|
98
105
|
const contentHeight = useStore(store, Dimensions.selectors.contentHeight);
|
|
99
106
|
|
|
100
107
|
/*
|
|
@@ -122,7 +129,10 @@ function useVirtualization(store, params, api) {
|
|
|
122
129
|
const updateRenderContext = React.useCallback(nextRenderContext => {
|
|
123
130
|
if (!areRenderContextsEqual(nextRenderContext, store.state.virtualization.renderContext)) {
|
|
124
131
|
store.set('virtualization', _extends({}, store.state.virtualization, {
|
|
125
|
-
renderContext: nextRenderContext
|
|
132
|
+
renderContext: nextRenderContext,
|
|
133
|
+
scrollPosition: {
|
|
134
|
+
current: _extends({}, scrollPosition.current)
|
|
135
|
+
}
|
|
126
136
|
}));
|
|
127
137
|
}
|
|
128
138
|
|
|
@@ -138,7 +148,7 @@ function useVirtualization(store, params, api) {
|
|
|
138
148
|
previousContextScrollPosition.current = scrollPosition.current;
|
|
139
149
|
}, [store, onRenderContextChange]);
|
|
140
150
|
const triggerUpdateRenderContext = useEventCallback(() => {
|
|
141
|
-
const scroller = refs.scroller.current;
|
|
151
|
+
const scroller = layout.refs.scroller.current;
|
|
142
152
|
if (!scroller) {
|
|
143
153
|
return undefined;
|
|
144
154
|
}
|
|
@@ -166,6 +176,11 @@ function useVirtualization(store, params, api) {
|
|
|
166
176
|
const didChangeDirection = scrollCache.direction !== direction;
|
|
167
177
|
const shouldUpdate = didCrossThreshold || didChangeDirection;
|
|
168
178
|
if (!shouldUpdate) {
|
|
179
|
+
store.set('virtualization', _extends({}, store.state.virtualization, {
|
|
180
|
+
scrollPosition: {
|
|
181
|
+
current: _extends({}, scrollPosition.current)
|
|
182
|
+
}
|
|
183
|
+
}));
|
|
169
184
|
return renderContext;
|
|
170
185
|
}
|
|
171
186
|
|
|
@@ -232,9 +247,6 @@ function useVirtualization(store, params, api) {
|
|
|
232
247
|
onScrollChange?.(scrollPosition.current, nextRenderContext);
|
|
233
248
|
}
|
|
234
249
|
});
|
|
235
|
-
const getOffsetTop = () => {
|
|
236
|
-
return rowsMeta.positions[renderContext.firstRowIndex] ?? 0;
|
|
237
|
-
};
|
|
238
250
|
|
|
239
251
|
/**
|
|
240
252
|
* HACK: unstable_rowTree fixes the issue described below, but does it by tightly coupling this
|
|
@@ -363,34 +375,13 @@ function useVirtualization(store, params, api) {
|
|
|
363
375
|
if (panel) {
|
|
364
376
|
rowElements.push(panel);
|
|
365
377
|
}
|
|
366
|
-
if (rowParams.position === undefined && isLastVisibleInSection) {
|
|
378
|
+
if (rowParams.position === undefined && isLastVisibleInSection && renderInfiniteLoadingTrigger) {
|
|
367
379
|
rowElements.push(renderInfiniteLoadingTrigger(id));
|
|
368
380
|
}
|
|
369
381
|
});
|
|
370
382
|
return rowElements;
|
|
371
383
|
};
|
|
372
|
-
const scrollerStyle = React.useMemo(() => ({
|
|
373
|
-
overflowX: !needsHorizontalScrollbar ? 'hidden' : undefined,
|
|
374
|
-
overflowY: autoHeight ? 'hidden' : undefined
|
|
375
|
-
}), [needsHorizontalScrollbar, autoHeight]);
|
|
376
|
-
const contentSize = React.useMemo(() => {
|
|
377
|
-
const size = {
|
|
378
|
-
width: needsHorizontalScrollbar ? columnsTotalWidth : 'auto',
|
|
379
|
-
flexBasis: contentHeight,
|
|
380
|
-
flexShrink: 0
|
|
381
|
-
};
|
|
382
|
-
if (size.flexBasis === 0) {
|
|
383
|
-
size.flexBasis = minimalContentHeight; // Give room to show the overlay when there no rows.
|
|
384
|
-
}
|
|
385
|
-
return size;
|
|
386
|
-
}, [columnsTotalWidth, contentHeight, needsHorizontalScrollbar, minimalContentHeight]);
|
|
387
384
|
const scrollRestoreCallback = React.useRef(null);
|
|
388
|
-
const contentNodeRef = React.useCallback(node => {
|
|
389
|
-
if (!node) {
|
|
390
|
-
return;
|
|
391
|
-
}
|
|
392
|
-
scrollRestoreCallback.current?.(columnsTotalWidth, contentHeight);
|
|
393
|
-
}, [columnsTotalWidth, contentHeight]);
|
|
394
385
|
useEnhancedEffect(() => {
|
|
395
386
|
if (!isRenderContextReady.current) {
|
|
396
387
|
return;
|
|
@@ -398,15 +389,15 @@ function useVirtualization(store, params, api) {
|
|
|
398
389
|
forceUpdateRenderContextCallback();
|
|
399
390
|
}, [enabledForColumns, enabledForRows, forceUpdateRenderContextCallback]);
|
|
400
391
|
useEnhancedEffect(() => {
|
|
401
|
-
if (refs.scroller.current) {
|
|
402
|
-
refs.scroller.current.scrollLeft = 0;
|
|
392
|
+
if (layout.refs.scroller.current) {
|
|
393
|
+
layout.refs.scroller.current.scrollLeft = 0;
|
|
403
394
|
}
|
|
404
|
-
}, [refs.scroller, scrollReset]);
|
|
395
|
+
}, [layout.refs.scroller, scrollReset]);
|
|
405
396
|
useRunOnce(renderContext !== EMPTY_RENDER_CONTEXT, () => {
|
|
406
397
|
onScrollChange?.(scrollPosition.current, renderContext);
|
|
407
398
|
isRenderContextReady.current = true;
|
|
408
|
-
if (initialState?.scroll && refs.scroller.current) {
|
|
409
|
-
const scroller = refs.scroller.current;
|
|
399
|
+
if (initialState?.scroll && layout.refs.scroller.current) {
|
|
400
|
+
const scroller = layout.refs.scroller.current;
|
|
410
401
|
const {
|
|
411
402
|
top,
|
|
412
403
|
left
|
|
@@ -449,20 +440,14 @@ function useVirtualization(store, params, api) {
|
|
|
449
440
|
}
|
|
450
441
|
});
|
|
451
442
|
useStoreEffect(store, Dimensions.selectors.dimensions, forceUpdateRenderContext);
|
|
452
|
-
|
|
453
|
-
if (
|
|
454
|
-
|
|
443
|
+
useEnhancedEffect(() => {
|
|
444
|
+
if (layout.refs.scroller) {
|
|
445
|
+
scrollRestoreCallback.current?.(columnsTotalWidth, contentHeight);
|
|
455
446
|
}
|
|
456
|
-
};
|
|
447
|
+
}, [layout.refs.scroller, columnsTotalWidth, contentHeight]);
|
|
457
448
|
const isFirstSizing = React.useRef(true);
|
|
458
|
-
const
|
|
459
|
-
|
|
460
|
-
if (!node) {
|
|
461
|
-
// Cleanup for R18
|
|
462
|
-
containerCleanup.current?.();
|
|
463
|
-
return;
|
|
464
|
-
}
|
|
465
|
-
refs.container.current = node;
|
|
449
|
+
const containerRef = useRefCallback(node => {
|
|
450
|
+
layout.refs.container.current = node;
|
|
466
451
|
const unsubscribe = observeRootNode(node, store, rootSize => {
|
|
467
452
|
if (rootSize.width === 0 && rootSize.height === 0 && store.state.rootSize.height !== 0 && store.state.rootSize.width !== 0) {
|
|
468
453
|
return;
|
|
@@ -476,98 +461,58 @@ function useVirtualization(store, params, api) {
|
|
|
476
461
|
api.debouncedUpdateDimensions();
|
|
477
462
|
}
|
|
478
463
|
});
|
|
479
|
-
|
|
464
|
+
return () => {
|
|
480
465
|
unsubscribe?.();
|
|
481
|
-
refs.container.current = null;
|
|
466
|
+
layout.refs.container.current = null;
|
|
482
467
|
};
|
|
483
|
-
if (reactMajor >= 19) {
|
|
484
|
-
/* eslint-disable-next-line consistent-return */
|
|
485
|
-
return containerCleanup.current;
|
|
486
|
-
}
|
|
487
468
|
});
|
|
488
|
-
const
|
|
489
|
-
|
|
490
|
-
if (!node) {
|
|
491
|
-
// Cleanup for R18
|
|
492
|
-
scrollerCleanup.current?.();
|
|
493
|
-
return;
|
|
494
|
-
}
|
|
495
|
-
scrollerCleanup.current?.();
|
|
496
|
-
refs.scroller.current = node;
|
|
469
|
+
const scrollerRef = useRefCallback(node => {
|
|
470
|
+
layout.refs.scroller.current = node;
|
|
497
471
|
const opts = {
|
|
498
472
|
passive: true
|
|
499
473
|
};
|
|
500
474
|
node.addEventListener('scroll', handleScroll, opts);
|
|
501
475
|
node.addEventListener('wheel', onWheel, opts);
|
|
502
476
|
node.addEventListener('touchmove', onTouchMove, opts);
|
|
503
|
-
|
|
477
|
+
return () => {
|
|
504
478
|
node.removeEventListener('scroll', handleScroll, opts);
|
|
505
479
|
node.removeEventListener('wheel', onWheel, opts);
|
|
506
480
|
node.removeEventListener('touchmove', onTouchMove, opts);
|
|
507
|
-
refs.scroller.current = null;
|
|
481
|
+
layout.refs.scroller.current = null;
|
|
508
482
|
};
|
|
509
|
-
if (reactMajor >= 19) {
|
|
510
|
-
/* eslint-disable-next-line consistent-return */
|
|
511
|
-
return scrollerCleanup.current;
|
|
512
|
-
}
|
|
513
483
|
});
|
|
514
|
-
const
|
|
515
|
-
|
|
516
|
-
|
|
484
|
+
const layoutParams = {
|
|
485
|
+
containerRef,
|
|
486
|
+
scrollerRef
|
|
487
|
+
};
|
|
488
|
+
const layoutAPI = layout.use(store, params, api, layoutParams);
|
|
489
|
+
const getters = _extends({
|
|
517
490
|
setPanels,
|
|
518
|
-
getOffsetTop,
|
|
519
491
|
getRows,
|
|
520
|
-
rows: params.rows
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
}),
|
|
524
|
-
getScrollerProps: () => ({
|
|
525
|
-
ref: scrollerRef,
|
|
526
|
-
style: scrollerStyle,
|
|
527
|
-
role: 'presentation',
|
|
528
|
-
// `tabIndex` shouldn't be used along role=presentation, but it fixes a Firefox bug
|
|
529
|
-
// https://github.com/mui/mui-x/pull/13891#discussion_r1683416024
|
|
530
|
-
tabIndex: platform.isFirefox ? -1 : undefined
|
|
531
|
-
}),
|
|
532
|
-
getContentProps: () => ({
|
|
533
|
-
ref: contentNodeRef,
|
|
534
|
-
style: contentSize,
|
|
535
|
-
role: 'presentation'
|
|
536
|
-
}),
|
|
537
|
-
getScrollbarVerticalProps: () => ({
|
|
538
|
-
ref: scrollbarVerticalRef,
|
|
539
|
-
scrollPosition
|
|
540
|
-
}),
|
|
541
|
-
getScrollbarHorizontalProps: () => ({
|
|
542
|
-
ref: scrollbarHorizontalRef,
|
|
543
|
-
scrollPosition
|
|
544
|
-
}),
|
|
545
|
-
getScrollAreaProps: () => ({
|
|
546
|
-
scrollPosition
|
|
547
|
-
})
|
|
548
|
-
};
|
|
549
|
-
|
|
550
|
-
/* Placeholder API functions for colspan & rowspan to re-implement */
|
|
551
|
-
|
|
552
|
-
const getCellColSpanInfo = () => {
|
|
553
|
-
throw new Error('Unimplemented: colspan feature is required');
|
|
554
|
-
};
|
|
555
|
-
const calculateColSpan = () => {
|
|
556
|
-
throw new Error('Unimplemented: colspan feature is required');
|
|
557
|
-
};
|
|
558
|
-
const getHiddenCellsOrigin = () => {
|
|
559
|
-
throw new Error('Unimplemented: rowspan feature is required');
|
|
560
|
-
};
|
|
561
|
-
return {
|
|
492
|
+
rows: params.rows
|
|
493
|
+
}, layoutAPI);
|
|
494
|
+
return _extends({
|
|
562
495
|
getters,
|
|
563
|
-
useVirtualization: () => useStore(store, state => state),
|
|
564
496
|
setPanels,
|
|
565
497
|
forceUpdateRenderContext,
|
|
566
|
-
scheduleUpdateRenderContext
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
498
|
+
scheduleUpdateRenderContext
|
|
499
|
+
}, createSpanningAPI());
|
|
500
|
+
}
|
|
501
|
+
function useRefCallback(fn) {
|
|
502
|
+
const refCleanup = React.useRef(undefined);
|
|
503
|
+
const refCallback = useEventCallback(node => {
|
|
504
|
+
if (!node) {
|
|
505
|
+
// Cleanup for R18
|
|
506
|
+
refCleanup.current?.();
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
refCleanup.current = fn(node);
|
|
510
|
+
if (reactMajor >= 19) {
|
|
511
|
+
/* eslint-disable-next-line consistent-return */
|
|
512
|
+
return refCleanup.current;
|
|
513
|
+
}
|
|
514
|
+
});
|
|
515
|
+
return refCallback;
|
|
571
516
|
}
|
|
572
517
|
function inputsSelector(store, params, api, enabledForRows, enabledForColumns) {
|
|
573
518
|
const dimensions = Dimensions.selectors.dimensions(store.state);
|
|
@@ -581,7 +526,7 @@ function inputsSelector(store, params, api, enabledForRows, enabledForColumns) {
|
|
|
581
526
|
api,
|
|
582
527
|
enabledForRows,
|
|
583
528
|
enabledForColumns,
|
|
584
|
-
autoHeight:
|
|
529
|
+
autoHeight: dimensions.autoHeight,
|
|
585
530
|
rowBufferPx: params.virtualization.rowBufferPx,
|
|
586
531
|
columnBufferPx: params.virtualization.columnBufferPx,
|
|
587
532
|
leftPinnedWidth: dimensions.leftPinnedWidth,
|
|
@@ -886,6 +831,24 @@ function getFirstNonSpannedColumnToRender({
|
|
|
886
831
|
}
|
|
887
832
|
return firstNonSpannedColumnToRender;
|
|
888
833
|
}
|
|
834
|
+
|
|
835
|
+
/** Placeholder API functions for colspan & rowspan to re-implement */
|
|
836
|
+
function createSpanningAPI() {
|
|
837
|
+
const getCellColSpanInfo = () => {
|
|
838
|
+
throw new Error('Unimplemented: colspan feature is required');
|
|
839
|
+
};
|
|
840
|
+
const calculateColSpan = () => {
|
|
841
|
+
throw new Error('Unimplemented: colspan feature is required');
|
|
842
|
+
};
|
|
843
|
+
const getHiddenCellsOrigin = () => {
|
|
844
|
+
throw new Error('Unimplemented: rowspan feature is required');
|
|
845
|
+
};
|
|
846
|
+
return {
|
|
847
|
+
getCellColSpanInfo,
|
|
848
|
+
calculateColSpan,
|
|
849
|
+
getHiddenCellsOrigin
|
|
850
|
+
};
|
|
851
|
+
}
|
|
889
852
|
export function roundToDecimalPlaces(value, decimals) {
|
|
890
853
|
return Math.round(value * 10 ** decimals) / 10 ** decimals;
|
|
891
854
|
}
|
package/esm/index.d.ts
CHANGED
package/esm/index.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @mui/x-virtualizer v0.2.
|
|
2
|
+
* @mui/x-virtualizer v0.2.12
|
|
3
3
|
*
|
|
4
4
|
* @license MIT
|
|
5
5
|
* This source code is licensed under the MIT license found in the
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*/
|
|
8
8
|
export * from "./useVirtualizer.js";
|
|
9
|
-
export * from "./features/index.js";
|
|
9
|
+
export * from "./features/index.js";
|
|
10
|
+
export * from "./constants.js";
|
package/esm/models/core.d.ts
CHANGED
|
@@ -62,6 +62,13 @@ export type ScrollPosition = {
|
|
|
62
62
|
top: number;
|
|
63
63
|
left: number;
|
|
64
64
|
};
|
|
65
|
+
export declare const ScrollPosition: {
|
|
66
|
+
EMPTY: {
|
|
67
|
+
top: number;
|
|
68
|
+
left: number;
|
|
69
|
+
};
|
|
70
|
+
equals: (a: ScrollPosition, b: ScrollPosition) => boolean;
|
|
71
|
+
};
|
|
65
72
|
export declare enum ScrollDirection {
|
|
66
73
|
NONE = 0,
|
|
67
74
|
UP = 1,
|
package/esm/models/core.js
CHANGED
|
@@ -22,6 +22,13 @@ export const PinnedColumns = {
|
|
|
22
22
|
right: []
|
|
23
23
|
}
|
|
24
24
|
};
|
|
25
|
+
export const ScrollPosition = {
|
|
26
|
+
EMPTY: {
|
|
27
|
+
top: 0,
|
|
28
|
+
left: 0
|
|
29
|
+
},
|
|
30
|
+
equals: (a, b) => a.top === b.top && a.left === b.left
|
|
31
|
+
};
|
|
25
32
|
export let ScrollDirection = /*#__PURE__*/function (ScrollDirection) {
|
|
26
33
|
ScrollDirection[ScrollDirection["NONE"] = 0] = "NONE";
|
|
27
34
|
ScrollDirection[ScrollDirection["UP"] = 1] = "UP";
|
|
@@ -65,6 +65,14 @@ export interface DimensionsState {
|
|
|
65
65
|
* Size of the bottom container.
|
|
66
66
|
*/
|
|
67
67
|
bottomContainerHeight: number;
|
|
68
|
+
/**
|
|
69
|
+
* Indicates that the container takes the height of its content.
|
|
70
|
+
*/
|
|
71
|
+
autoHeight: boolean;
|
|
72
|
+
/**
|
|
73
|
+
* Minimal height to display the content area.
|
|
74
|
+
*/
|
|
75
|
+
minimalContentHeight: string | number | undefined;
|
|
68
76
|
}
|
|
69
77
|
/**
|
|
70
78
|
* The rows total height and positions.
|
package/esm/useVirtualizer.d.ts
CHANGED
|
@@ -1,25 +1,21 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { integer
|
|
2
|
+
import { integer } from '@mui/x-internals/types';
|
|
3
3
|
import { Store } from '@mui/x-internals/store';
|
|
4
4
|
import { Colspan } from "./features/colspan.js";
|
|
5
5
|
import { Dimensions } from "./features/dimensions.js";
|
|
6
6
|
import { Rowspan } from "./features/rowspan.js";
|
|
7
|
-
import { Virtualization } from "./features/virtualization.js";
|
|
7
|
+
import { Virtualization } from "./features/virtualization/index.js";
|
|
8
|
+
import type { Layout } from "./features/virtualization/layout.js";
|
|
8
9
|
import type { HeightEntry, RowSpacing } from "./models/dimensions.js";
|
|
9
10
|
import type { ColspanParams } from "./features/colspan.js";
|
|
10
11
|
import type { DimensionsParams } from "./features/dimensions.js";
|
|
11
|
-
import type { VirtualizationParams } from "./features/virtualization.js";
|
|
12
|
+
import type { VirtualizationParams } from "./features/virtualization/index.js";
|
|
12
13
|
import { ColumnWithWidth, FocusedCell, Size, PinnedRows, PinnedColumns, RenderContext, Row, RowEntry } from "./models/index.js";
|
|
13
14
|
export type Virtualizer = ReturnType<typeof useVirtualizer>;
|
|
14
|
-
export type VirtualScrollerCompat = Virtualization.State['getters'];
|
|
15
|
-
export type BaseState = Virtualization.State & Dimensions.State;
|
|
16
|
-
export type VirtualizerParams = {
|
|
17
|
-
|
|
18
|
-
container: RefObject<HTMLDivElement | null>;
|
|
19
|
-
scroller: RefObject<HTMLDivElement | null>;
|
|
20
|
-
scrollbarVertical: RefObject<HTMLDivElement | null>;
|
|
21
|
-
scrollbarHorizontal: RefObject<HTMLDivElement | null>;
|
|
22
|
-
};
|
|
15
|
+
export type VirtualScrollerCompat<L extends Layout = Layout> = Virtualization.State<L>['getters'];
|
|
16
|
+
export type BaseState<L extends Layout = Layout> = Virtualization.State<L> & Dimensions.State;
|
|
17
|
+
export type VirtualizerParams<L extends Layout = Layout> = {
|
|
18
|
+
layout: L;
|
|
23
19
|
dimensions: DimensionsParams;
|
|
24
20
|
virtualization: VirtualizationParams;
|
|
25
21
|
colspan?: ColspanParams;
|
|
@@ -29,7 +25,7 @@ export type VirtualizerParams = {
|
|
|
29
25
|
left: number;
|
|
30
26
|
};
|
|
31
27
|
rowSpanning?: Rowspan.State['rowSpanning'];
|
|
32
|
-
virtualization?: Partial<Virtualization.State['virtualization']>;
|
|
28
|
+
virtualization?: Partial<Virtualization.State<L>['virtualization']>;
|
|
33
29
|
};
|
|
34
30
|
/** current page rows */
|
|
35
31
|
rows: RowEntry[];
|
|
@@ -39,13 +35,11 @@ export type VirtualizerParams = {
|
|
|
39
35
|
lastRowIndex: integer;
|
|
40
36
|
} | null;
|
|
41
37
|
rowCount: integer;
|
|
42
|
-
columns
|
|
38
|
+
columns?: ColumnWithWidth[];
|
|
43
39
|
pinnedRows?: PinnedRows;
|
|
44
40
|
pinnedColumns?: PinnedColumns;
|
|
45
|
-
autoHeight: boolean;
|
|
46
41
|
disableHorizontalScroll?: boolean;
|
|
47
42
|
disableVerticalScroll?: boolean;
|
|
48
|
-
minimalContentHeight?: number | string;
|
|
49
43
|
getRowHeight?: (row: RowEntry) => number | null | undefined | 'auto';
|
|
50
44
|
/**
|
|
51
45
|
* Function that returns the estimated height for a row.
|
|
@@ -68,7 +62,7 @@ export type VirtualizerParams = {
|
|
|
68
62
|
*/
|
|
69
63
|
applyRowHeight?: (entry: HeightEntry, rowEntry: RowEntry) => void;
|
|
70
64
|
virtualizeColumnsWithAutoRowHeight?: boolean;
|
|
71
|
-
resizeThrottleMs
|
|
65
|
+
resizeThrottleMs?: number;
|
|
72
66
|
onResize?: (lastSize: Size) => void;
|
|
73
67
|
onWheel?: (event: React.WheelEvent) => void;
|
|
74
68
|
onTouchMove?: (event: React.TouchEvent) => void;
|
|
@@ -94,10 +88,15 @@ export type VirtualizerParams = {
|
|
|
94
88
|
isVirtualFocusRow: boolean;
|
|
95
89
|
showBottomBorder: boolean;
|
|
96
90
|
}) => React.ReactElement;
|
|
97
|
-
renderInfiniteLoadingTrigger
|
|
91
|
+
renderInfiniteLoadingTrigger?: (id: any) => React.ReactElement;
|
|
92
|
+
};
|
|
93
|
+
type RequiredFields<T, K extends keyof T> = T & Required<Pick<T, K>>;
|
|
94
|
+
export type ParamsWithDefaults = RequiredFields<VirtualizerParams, 'resizeThrottleMs' | 'columns'> & {
|
|
95
|
+
dimensions: RequiredFields<VirtualizerParams['dimensions'], 'columnsTotalWidth' | 'leftPinnedWidth' | 'rightPinnedWidth' | 'topPinnedHeight' | 'bottomPinnedHeight' | 'autoHeight'>;
|
|
96
|
+
virtualization: RequiredFields<VirtualizerParams['virtualization'], 'isRtl' | 'rowBufferPx' | 'columnBufferPx'>;
|
|
98
97
|
};
|
|
99
|
-
export declare const useVirtualizer: (params: VirtualizerParams) => {
|
|
100
|
-
store: Store<Dimensions.State & Virtualization.State & Colspan.State & Rowspan.State>;
|
|
98
|
+
export declare const useVirtualizer: <L extends Layout = Layout>(params: VirtualizerParams<L>) => {
|
|
99
|
+
store: Store<Dimensions.State & Virtualization.State<L> & Colspan.State & Rowspan.State>;
|
|
101
100
|
api: {
|
|
102
101
|
updateDimensions: (firstUpdate?: boolean) => void;
|
|
103
102
|
debouncedUpdateDimensions: (((firstUpdate?: boolean) => void) & import("@mui/x-internals/throttle").Cancelable) | undefined;
|
|
@@ -113,57 +112,13 @@ export declare const useVirtualizer: (params: VirtualizerParams) => {
|
|
|
113
112
|
resetRowHeights: () => void;
|
|
114
113
|
};
|
|
115
114
|
} & {
|
|
116
|
-
getters: {
|
|
117
|
-
setPanels: React.Dispatch<React.SetStateAction<Readonly<Map<any, React.ReactNode>>>>;
|
|
118
|
-
getOffsetTop: () => number;
|
|
119
|
-
getRows: (rowParams?: {
|
|
120
|
-
rows?: RowEntry[];
|
|
121
|
-
position?: import("./models/index.js").PinnedRowPosition;
|
|
122
|
-
renderContext?: RenderContext;
|
|
123
|
-
}, unstable_rowTree?: Record<import("./models/index.js").RowId, any>) => React.ReactNode[];
|
|
124
|
-
rows: RowEntry[];
|
|
125
|
-
getContainerProps: () => {
|
|
126
|
-
ref: (node: HTMLDivElement | null) => (() => void | undefined) | undefined;
|
|
127
|
-
};
|
|
128
|
-
getScrollerProps: () => {
|
|
129
|
-
ref: (node: HTMLDivElement | null) => (() => void | undefined) | undefined;
|
|
130
|
-
style: React.CSSProperties;
|
|
131
|
-
role: string;
|
|
132
|
-
tabIndex: number | undefined;
|
|
133
|
-
};
|
|
134
|
-
getContentProps: () => {
|
|
135
|
-
ref: (node: HTMLDivElement | null) => void;
|
|
136
|
-
style: React.CSSProperties;
|
|
137
|
-
role: string;
|
|
138
|
-
};
|
|
139
|
-
getScrollbarVerticalProps: () => {
|
|
140
|
-
ref: (node: HTMLDivElement | null) => void;
|
|
141
|
-
scrollPosition: React.RefObject<{
|
|
142
|
-
top: number;
|
|
143
|
-
left: number;
|
|
144
|
-
}>;
|
|
145
|
-
};
|
|
146
|
-
getScrollbarHorizontalProps: () => {
|
|
147
|
-
ref: (node: HTMLDivElement | null) => void;
|
|
148
|
-
scrollPosition: React.RefObject<{
|
|
149
|
-
top: number;
|
|
150
|
-
left: number;
|
|
151
|
-
}>;
|
|
152
|
-
};
|
|
153
|
-
getScrollAreaProps: () => {
|
|
154
|
-
scrollPosition: React.RefObject<{
|
|
155
|
-
top: number;
|
|
156
|
-
left: number;
|
|
157
|
-
}>;
|
|
158
|
-
};
|
|
159
|
-
};
|
|
160
|
-
useVirtualization: () => BaseState;
|
|
161
|
-
setPanels: React.Dispatch<React.SetStateAction<Readonly<Map<any, React.ReactNode>>>>;
|
|
162
|
-
forceUpdateRenderContext: () => void;
|
|
163
|
-
scheduleUpdateRenderContext: () => void;
|
|
164
115
|
getCellColSpanInfo: (rowId: import("./models/index.js").RowId, columnIndex: integer) => import("./models/index.js").CellColSpanInfo;
|
|
165
116
|
calculateColSpan: (rowId: import("./models/index.js").RowId, minFirstColumn: integer, maxLastColumn: integer, columns: ColumnWithWidth[]) => void;
|
|
166
117
|
getHiddenCellsOrigin: () => Record<import("./models/index.js").RowId, Record<number, number>>;
|
|
118
|
+
getters: any;
|
|
119
|
+
setPanels: React.Dispatch<React.SetStateAction<Readonly<Map<any, React.ReactNode>>>>;
|
|
120
|
+
forceUpdateRenderContext: () => void;
|
|
121
|
+
scheduleUpdateRenderContext: () => void;
|
|
167
122
|
} & {
|
|
168
123
|
resetColSpan: () => void;
|
|
169
124
|
getCellColSpanInfo: (rowId: import("./models/index.js").RowId, columnIndex: integer) => import("./models/index.js").CellColSpanInfo | undefined;
|
|
@@ -173,4 +128,5 @@ export declare const useVirtualizer: (params: VirtualizerParams) => {
|
|
|
173
128
|
} & {
|
|
174
129
|
getViewportPageSize: () => number;
|
|
175
130
|
};
|
|
176
|
-
};
|
|
131
|
+
};
|
|
132
|
+
export {};
|
package/esm/useVirtualizer.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
1
2
|
import useLazyRef from '@mui/utils/useLazyRef';
|
|
2
3
|
import { Store } from '@mui/x-internals/store';
|
|
3
4
|
import { Colspan } from "./features/colspan.js";
|
|
4
5
|
import { Dimensions } from "./features/dimensions.js";
|
|
5
6
|
import { Keyboard } from "./features/keyboard.js";
|
|
6
7
|
import { Rowspan } from "./features/rowspan.js";
|
|
7
|
-
import { Virtualization } from "./features/virtualization.js";
|
|
8
|
+
import { Virtualization } from "./features/virtualization/index.js";
|
|
9
|
+
import { DEFAULT_PARAMS } from "./constants.js";
|
|
8
10
|
|
|
9
11
|
/* eslint-disable jsdoc/require-param-type */
|
|
10
12
|
/* eslint-disable jsdoc/require-param-description */
|
|
@@ -12,15 +14,30 @@ import { Virtualization } from "./features/virtualization.js";
|
|
|
12
14
|
|
|
13
15
|
const FEATURES = [Dimensions, Virtualization, Colspan, Rowspan, Keyboard];
|
|
14
16
|
export const useVirtualizer = params => {
|
|
17
|
+
const paramsWithDefault = mergeDefaults(params, DEFAULT_PARAMS);
|
|
15
18
|
const store = useLazyRef(() => {
|
|
16
|
-
return new Store(FEATURES.map(f => f.initialize(
|
|
19
|
+
return new Store(FEATURES.map(f => f.initialize(paramsWithDefault)).reduce((state, partial) => Object.assign(state, partial), {}));
|
|
17
20
|
}).current;
|
|
18
21
|
const api = {};
|
|
19
22
|
for (const feature of FEATURES) {
|
|
20
|
-
Object.assign(api, feature.use(store,
|
|
23
|
+
Object.assign(api, feature.use(store, paramsWithDefault, api));
|
|
21
24
|
}
|
|
22
25
|
return {
|
|
23
26
|
store,
|
|
24
27
|
api
|
|
25
28
|
};
|
|
26
|
-
};
|
|
29
|
+
};
|
|
30
|
+
function mergeDefaults(params, defaults) {
|
|
31
|
+
const result = _extends({}, params);
|
|
32
|
+
for (const key in defaults) {
|
|
33
|
+
if (Object.hasOwn(defaults, key)) {
|
|
34
|
+
const value = defaults[key];
|
|
35
|
+
if (value !== null && typeof value === 'object' && !Array.isArray(value)) {
|
|
36
|
+
result[key] = mergeDefaults(params[key] ?? {}, value);
|
|
37
|
+
} else {
|
|
38
|
+
result[key] = params[key] ?? value;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return result;
|
|
43
|
+
}
|
package/features/colspan.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Store } from '@mui/x-internals/store';
|
|
2
2
|
import type { integer } from '@mui/x-internals/types';
|
|
3
|
-
import type { BaseState,
|
|
3
|
+
import type { BaseState, ParamsWithDefaults } from "../useVirtualizer.js";
|
|
4
4
|
import type { ColumnWithWidth, RowId } from "../models/index.js";
|
|
5
5
|
import type { CellColSpanInfo } from "../models/colspan.js";
|
|
6
|
-
import { Virtualization } from "./virtualization.js";
|
|
6
|
+
import { Virtualization } from "./virtualization/index.js";
|
|
7
7
|
type ColumnIndex = number;
|
|
8
8
|
type ColspanMap = Map<RowId, Record<ColumnIndex, CellColSpanInfo>>;
|
|
9
9
|
export type ColspanParams = {
|
|
@@ -21,10 +21,10 @@ export declare namespace Colspan {
|
|
|
21
21
|
};
|
|
22
22
|
type API = ReturnType<typeof useColspan>;
|
|
23
23
|
}
|
|
24
|
-
declare function initializeState(_params:
|
|
24
|
+
declare function initializeState(_params: ParamsWithDefaults): {
|
|
25
25
|
colspanMap: Map<any, any>;
|
|
26
26
|
};
|
|
27
|
-
declare function useColspan(store: Store<BaseState & Colspan.State>, params:
|
|
27
|
+
declare function useColspan(store: Store<BaseState & Colspan.State>, params: ParamsWithDefaults, api: Virtualization.API): {
|
|
28
28
|
resetColSpan: () => void;
|
|
29
29
|
getCellColSpanInfo: (rowId: RowId, columnIndex: integer) => CellColSpanInfo | undefined;
|
|
30
30
|
calculateColSpan: (rowId: RowId, minFirstColumn: integer, maxLastColumn: integer, columns: ColumnWithWidth[]) => void;
|