beautiful-grid 1.0.2 → 1.0.3
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/README.md +1 -1
- package/cjs/components/Table.js +111 -106
- package/cjs/components/selection/CellSelectionOverlayLayer.js +5 -5
- package/cjs/utils/coordinate.js +10 -10
- package/cjs/utils/index.js +1 -0
- package/cjs/utils/virtualScrollWindow.js +67 -0
- package/esm/components/Table.js +110 -106
- package/esm/components/selection/CellSelectionOverlayLayer.js +5 -5
- package/esm/utils/coordinate.js +4 -4
- package/esm/utils/index.js +1 -0
- package/esm/utils/virtualScrollWindow.js +59 -0
- package/package.json +1 -1
- package/types/components/selection/CellSelectionOverlay.d.ts +1 -0
- package/types/components/selection/CellSelectionOverlayLayer.d.ts +2 -1
- package/types/utils/coordinate.d.ts +5 -1
- package/types/utils/index.d.ts +1 -0
- package/types/utils/virtualScrollWindow.d.ts +24 -0
package/esm/components/Table.js
CHANGED
|
@@ -3,7 +3,7 @@ import { useCallback, useEffect, useRef } from 'react';
|
|
|
3
3
|
import { useShallow } from 'zustand/react/shallow';
|
|
4
4
|
import { useAppStore } from '../store';
|
|
5
5
|
import { BGridDataItemStatus, } from '../types';
|
|
6
|
-
import { getCellValueByRowKey, getFrozenColumnsWidth, getVisibleScrollableRowRange, isCheckboxValueChecked, markCellEdited, markCellValueChanged, resolveLogicalCell, shouldRenderBottomBar, } from '../utils';
|
|
6
|
+
import { getCellValueByRowKey, getFrozenColumnsWidth, getVisibleScrollableRowRange, getVirtualScrollWindowMetrics, getVirtualScrollWindowPosition, isCheckboxValueChecked, markCellEdited, markCellValueChanged, rebaseVirtualScrollWindow, resolveLogicalCell, shouldRenderBottomBar, } from '../utils';
|
|
7
7
|
import { clamp, ensureCellVisible } from '../utils/coordinate';
|
|
8
8
|
import Loading from './Loading';
|
|
9
9
|
import TableBody from './TableBody';
|
|
@@ -183,6 +183,23 @@ function Table(props) {
|
|
|
183
183
|
const trHeight = itemHeight + itemPadding * 2;
|
|
184
184
|
const scrollableBodyHeight = Math.max(contentBodyHeight - frozenRowsHeight, 0);
|
|
185
185
|
const mainViewportWidth = Math.max(width - (frozenColumnsWidth ?? 0), 0);
|
|
186
|
+
const logicalBodyContentHeight = data.length * trHeight;
|
|
187
|
+
const virtualScrollWindowMetrics = React.useMemo(() => getVirtualScrollWindowMetrics({
|
|
188
|
+
logicalContentHeight: logicalBodyContentHeight,
|
|
189
|
+
viewportHeight: contentBodyHeight,
|
|
190
|
+
enabled: scrollbar.variant !== 'native',
|
|
191
|
+
}), [contentBodyHeight, logicalBodyContentHeight, scrollbar.variant]);
|
|
192
|
+
const [virtualScrollBase, setVirtualScrollBase] = React.useState(0);
|
|
193
|
+
const virtualScrollBaseRef = useRef(0);
|
|
194
|
+
const containerRef = useRef(null);
|
|
195
|
+
const searchPopoverRef = useRef(null);
|
|
196
|
+
const editorPortalRef = useRef(null);
|
|
197
|
+
const bodyContainerRef = useRef(null);
|
|
198
|
+
const scrollContainerRef = useRef(null);
|
|
199
|
+
const logicalVerticalScrollState = React.useMemo(() => ({
|
|
200
|
+
scrollTop,
|
|
201
|
+
scrollHeight: virtualScrollWindowMetrics.logicalContentHeight,
|
|
202
|
+
}), [scrollTop, virtualScrollWindowMetrics.logicalContentHeight]);
|
|
186
203
|
const hasMultiCellSelection = React.useMemo(() => cellSelectionRanges.length > 1 ||
|
|
187
204
|
cellSelectionRanges.some(range => {
|
|
188
205
|
const normalized = normalizeCellSelectionRange(range);
|
|
@@ -273,7 +290,7 @@ function Table(props) {
|
|
|
273
290
|
top: topQuadrant ? 0 : scrollTop,
|
|
274
291
|
width: leftQuadrant ? frozenColumnsWidth ?? 0 : mainViewportWidth,
|
|
275
292
|
height: topQuadrant ? frozenRowsHeight : scrollableBodyHeight,
|
|
276
|
-
} }));
|
|
293
|
+
}, offsetTop: !topQuadrant && virtualScrollWindowMetrics.enabled ? virtualScrollBase : 0 }));
|
|
277
294
|
};
|
|
278
295
|
const visibleScrollableRows = React.useMemo(() => getVisibleScrollableRowRange({
|
|
279
296
|
scrollTop,
|
|
@@ -288,15 +305,14 @@ function Table(props) {
|
|
|
288
305
|
startRowIndex: visibleScrollableRows.startRowIndex,
|
|
289
306
|
endRowIndex: visibleScrollableRows.endRowIndex,
|
|
290
307
|
}), [visibleScrollableRows.endRowIndex, visibleScrollableRows.startRowIndex]);
|
|
291
|
-
const frozenScrollableBodyStyle = React.useMemo(() => ({
|
|
292
|
-
|
|
293
|
-
|
|
308
|
+
const frozenScrollableBodyStyle = React.useMemo(() => ({
|
|
309
|
+
top: virtualScrollWindowMetrics.enabled
|
|
310
|
+
? visibleScrollableRows.paddingTop - virtualScrollBase
|
|
311
|
+
: visibleScrollableRows.paddingTop,
|
|
312
|
+
}), [virtualScrollBase, virtualScrollWindowMetrics.enabled, visibleScrollableRows.paddingTop]);
|
|
294
313
|
const warnedContextMenuIdsRef = useRef(new Set());
|
|
295
314
|
const warnedContextMenuFactoryRef = useRef(false);
|
|
296
|
-
const editorPortalRef = useRef(null);
|
|
297
315
|
const editorPortalContext = React.useMemo(() => ({ gridRef: containerRef, portalRef: editorPortalRef }), []);
|
|
298
|
-
const bodyContainerRef = useRef(null);
|
|
299
|
-
const scrollContainerRef = useRef(null);
|
|
300
316
|
const rowReorderController = useRowReorderController({
|
|
301
317
|
containerRef,
|
|
302
318
|
bodyContainerRef,
|
|
@@ -404,7 +420,8 @@ function Table(props) {
|
|
|
404
420
|
const stickyBottomHeight = summary?.position === 'bottom' ? summaryHeight : 0;
|
|
405
421
|
const stickyFixedHeight = stickyTopHeight + stickyBottomHeight;
|
|
406
422
|
const scrollViewportHeight = contentBodyHeight + stickyFixedHeight;
|
|
407
|
-
const
|
|
423
|
+
const physicalScrollableRowsHeight = Math.max(virtualScrollWindowMetrics.physicalContentHeight - frozenRowsHeight, 0);
|
|
424
|
+
const scrollPlaneHeight = stickyFixedHeight + virtualScrollWindowMetrics.physicalContentHeight;
|
|
408
425
|
const scrollPlaneContentWidth = (frozenColumnsWidth ?? 0) + scrollableColumnsWidth;
|
|
409
426
|
const scrollPlaneWidth = Math.max(width, scrollPlaneContentWidth);
|
|
410
427
|
const customVerticalScrollbarGutter = scrollbar.vertical.visible && scrollbar.variant === 'classic'
|
|
@@ -415,7 +432,18 @@ function Table(props) {
|
|
|
415
432
|
const scrollPlaneMinWidth = customVerticalScrollbarGutter
|
|
416
433
|
? `max(100%, calc(${scrollPlaneContentWidth}px + ${customVerticalScrollbarGutter}))`
|
|
417
434
|
: scrollPlaneWidth;
|
|
418
|
-
const
|
|
435
|
+
const measuredScrollbarMetrics = useScrollbarMetrics(scrollContainerRef, [data.length, itemHeight, itemPadding, contentBodyHeight, width], scrollPlaneContentWidth, stickyFixedHeight);
|
|
436
|
+
const scrollbarMetrics = React.useMemo(() => virtualScrollWindowMetrics.enabled
|
|
437
|
+
? {
|
|
438
|
+
...measuredScrollbarMetrics,
|
|
439
|
+
vertical: {
|
|
440
|
+
viewportSize: contentBodyHeight,
|
|
441
|
+
contentSize: virtualScrollWindowMetrics.logicalContentHeight,
|
|
442
|
+
maxScroll: virtualScrollWindowMetrics.logicalMaxScroll,
|
|
443
|
+
hasOverflow: virtualScrollWindowMetrics.logicalMaxScroll > 1,
|
|
444
|
+
},
|
|
445
|
+
}
|
|
446
|
+
: measuredScrollbarMetrics, [contentBodyHeight, measuredScrollbarMetrics, virtualScrollWindowMetrics]);
|
|
419
447
|
const measuredVerticalScrollbarGutter = customVerticalScrollbarGutter && scrollbarMetrics.horizontal.hasOverflow
|
|
420
448
|
? Math.max(scrollbarMetrics.horizontal.contentSize - scrollPlaneContentWidth, 0)
|
|
421
449
|
: 0;
|
|
@@ -435,11 +463,6 @@ function Table(props) {
|
|
|
435
463
|
scrollContainerRef.current.scrollLeft = offset;
|
|
436
464
|
}
|
|
437
465
|
}, []);
|
|
438
|
-
const handleScrollTopChange = useCallback((offset) => {
|
|
439
|
-
if (scrollContainerRef.current) {
|
|
440
|
-
scrollContainerRef.current.scrollTop = offset;
|
|
441
|
-
}
|
|
442
|
-
}, []);
|
|
443
466
|
const latestScrollRef = useRef({ top: scrollTop, left: scrollLeft });
|
|
444
467
|
const latestCommittedScrollRef = useRef({ top: scrollTop, left: scrollLeft });
|
|
445
468
|
const scrollRafRef = useRef(null);
|
|
@@ -456,6 +479,7 @@ function Table(props) {
|
|
|
456
479
|
frozenRowCount,
|
|
457
480
|
frozenColumnsWidth: frozenColumnsWidth ?? 0,
|
|
458
481
|
frozenRowsHeight,
|
|
482
|
+
scrollTop,
|
|
459
483
|
trHeight,
|
|
460
484
|
});
|
|
461
485
|
useEffect(() => {
|
|
@@ -466,9 +490,10 @@ function Table(props) {
|
|
|
466
490
|
frozenRowCount,
|
|
467
491
|
frozenColumnsWidth: frozenColumnsWidth ?? 0,
|
|
468
492
|
frozenRowsHeight,
|
|
493
|
+
scrollTop,
|
|
469
494
|
trHeight,
|
|
470
495
|
};
|
|
471
|
-
}, [columns, data.length, props.frozenColumnIndex, frozenColumnsWidth, frozenRowCount, frozenRowsHeight, trHeight]);
|
|
496
|
+
}, [columns, data.length, props.frozenColumnIndex, frozenColumnsWidth, frozenRowCount, frozenRowsHeight, scrollTop, trHeight]);
|
|
472
497
|
const markScrollActive = useCallback(() => {
|
|
473
498
|
containerRef.current?.setAttribute('data-bgrid-scrolling', 'true');
|
|
474
499
|
if (scrollIdleTimerRef.current !== null)
|
|
@@ -478,6 +503,27 @@ function Table(props) {
|
|
|
478
503
|
containerRef.current?.removeAttribute('data-bgrid-scrolling');
|
|
479
504
|
}, SCROLL_IDLE_DELAY);
|
|
480
505
|
}, []);
|
|
506
|
+
const commitScroll = useCallback((top, left) => {
|
|
507
|
+
const scrollContainer = scrollContainerRef.current;
|
|
508
|
+
if (!scrollContainer)
|
|
509
|
+
return;
|
|
510
|
+
const position = getVirtualScrollWindowPosition(top, virtualScrollWindowMetrics);
|
|
511
|
+
if (virtualScrollBaseRef.current !== position.base) {
|
|
512
|
+
virtualScrollBaseRef.current = position.base;
|
|
513
|
+
setVirtualScrollBase(position.base);
|
|
514
|
+
}
|
|
515
|
+
if (scrollContainer.scrollTop !== position.physicalScrollTop) {
|
|
516
|
+
scrollContainer.scrollTop = position.physicalScrollTop;
|
|
517
|
+
}
|
|
518
|
+
if (scrollContainer.scrollLeft !== left)
|
|
519
|
+
scrollContainer.scrollLeft = left;
|
|
520
|
+
latestScrollRef.current = { top: position.logicalScrollTop, left };
|
|
521
|
+
latestCommittedScrollRef.current = { top: position.logicalScrollTop, left };
|
|
522
|
+
setScroll(position.logicalScrollTop, left);
|
|
523
|
+
}, [setScroll, virtualScrollWindowMetrics]);
|
|
524
|
+
const handleScrollTopChange = useCallback((offset) => {
|
|
525
|
+
commitScroll(offset, scrollContainerRef.current?.scrollLeft ?? scrollLeft);
|
|
526
|
+
}, [commitScroll, scrollLeft]);
|
|
481
527
|
const scheduleScrollFrame = useCallback(() => {
|
|
482
528
|
if (scrollRafRef.current !== null)
|
|
483
529
|
return;
|
|
@@ -486,90 +532,42 @@ function Table(props) {
|
|
|
486
532
|
const scrollContainer = scrollContainerRef.current;
|
|
487
533
|
if (!scrollContainer)
|
|
488
534
|
return;
|
|
489
|
-
const { scrollTop, scrollLeft } = scrollContainer;
|
|
490
|
-
|
|
535
|
+
const { scrollTop: physicalScrollTop, scrollLeft } = scrollContainer;
|
|
536
|
+
const position = rebaseVirtualScrollWindow(virtualScrollBaseRef.current, physicalScrollTop, virtualScrollWindowMetrics);
|
|
537
|
+
if (virtualScrollBaseRef.current !== position.base) {
|
|
538
|
+
virtualScrollBaseRef.current = position.base;
|
|
539
|
+
setVirtualScrollBase(position.base);
|
|
540
|
+
}
|
|
541
|
+
if (physicalScrollTop !== position.physicalScrollTop) {
|
|
542
|
+
scrollContainer.scrollTop = position.physicalScrollTop;
|
|
543
|
+
}
|
|
544
|
+
const logicalScrollTop = position.logicalScrollTop;
|
|
545
|
+
latestScrollRef.current = { top: logicalScrollTop, left: scrollLeft };
|
|
491
546
|
const { top: committedTop, left: committedLeft } = latestCommittedScrollRef.current;
|
|
492
|
-
if (committedTop !==
|
|
493
|
-
latestCommittedScrollRef.current = { top:
|
|
494
|
-
setScroll(
|
|
547
|
+
if (committedTop !== logicalScrollTop || committedLeft !== scrollLeft) {
|
|
548
|
+
latestCommittedScrollRef.current = { top: logicalScrollTop, left: scrollLeft };
|
|
549
|
+
setScroll(logicalScrollTop, scrollLeft);
|
|
495
550
|
}
|
|
496
551
|
if (containerRef.current?.hasAttribute('data-bgrid-scrolling')) {
|
|
497
552
|
scrollRafRef.current = requestAnimationFrame(pollNativeScrollPosition);
|
|
498
553
|
}
|
|
499
554
|
};
|
|
500
555
|
scrollRafRef.current = requestAnimationFrame(pollNativeScrollPosition);
|
|
501
|
-
}, [setScroll]);
|
|
556
|
+
}, [setScroll, virtualScrollWindowMetrics]);
|
|
502
557
|
const onScroll = useCallback(() => {
|
|
503
558
|
if (scrollContainerRef.current) {
|
|
504
|
-
const { scrollTop, scrollLeft } = scrollContainerRef.current;
|
|
505
|
-
latestScrollRef.current = { top: scrollTop, left: scrollLeft };
|
|
506
559
|
markScrollActive();
|
|
507
560
|
scheduleScrollFrame();
|
|
508
561
|
}
|
|
509
562
|
}, [markScrollActive, scheduleScrollFrame]);
|
|
510
|
-
const onWheel = useCallback(evt => {
|
|
511
|
-
const scrollContainer = scrollContainerRef.current;
|
|
512
|
-
if (!scrollContainer)
|
|
513
|
-
return;
|
|
514
|
-
const delta = { x: 0, y: 0 };
|
|
515
|
-
if (evt.detail) {
|
|
516
|
-
delta.y = evt.detail * 10;
|
|
517
|
-
}
|
|
518
|
-
else if (typeof evt.deltaY === 'undefined') {
|
|
519
|
-
delta.y = -evt.wheelDelta;
|
|
520
|
-
delta.x = 0;
|
|
521
|
-
}
|
|
522
|
-
else {
|
|
523
|
-
delta.y = evt.deltaY;
|
|
524
|
-
delta.x = evt.deltaX;
|
|
525
|
-
}
|
|
526
|
-
if (evt.deltaMode === 1) {
|
|
527
|
-
delta.y = delta.y * 16;
|
|
528
|
-
delta.x = delta.x * 16;
|
|
529
|
-
}
|
|
530
|
-
else if (evt.deltaMode === 2) {
|
|
531
|
-
delta.y = delta.y * scrollContainer.clientHeight;
|
|
532
|
-
delta.x = delta.x * scrollContainer.clientWidth;
|
|
533
|
-
}
|
|
534
|
-
const maxScrollTop = Math.max(scrollContainer.scrollHeight - scrollContainer.clientHeight, 0);
|
|
535
|
-
const maxScrollLeft = Math.max(scrollContainer.scrollWidth - scrollContainer.clientWidth, 0);
|
|
536
|
-
const nextScrollTop = Math.min(maxScrollTop, Math.max(0, scrollContainer.scrollTop + delta.y));
|
|
537
|
-
const nextScrollLeft = Math.min(maxScrollLeft, Math.max(0, scrollContainer.scrollLeft + delta.x));
|
|
538
|
-
const didScrollTop = nextScrollTop !== scrollContainer.scrollTop;
|
|
539
|
-
const didScrollLeft = nextScrollLeft !== scrollContainer.scrollLeft;
|
|
540
|
-
const isVertical = Math.abs(delta.y) > Math.abs(delta.x);
|
|
541
|
-
if (isVertical) {
|
|
542
|
-
if (!didScrollTop)
|
|
543
|
-
return;
|
|
544
|
-
}
|
|
545
|
-
else {
|
|
546
|
-
if (!didScrollLeft)
|
|
547
|
-
return;
|
|
548
|
-
}
|
|
549
|
-
evt.preventDefault();
|
|
550
|
-
if (didScrollTop)
|
|
551
|
-
scrollContainer.scrollTop = nextScrollTop;
|
|
552
|
-
if (didScrollLeft)
|
|
553
|
-
scrollContainer.scrollLeft = nextScrollLeft;
|
|
554
|
-
}, []);
|
|
555
563
|
const resetScrollPosition = useCallback((type) => {
|
|
556
|
-
if (type === 'all' || type === 'left')
|
|
557
|
-
scrollContainerRef.current?.scrollTo({ left: 0 });
|
|
558
|
-
if (type === 'all' || type === 'top')
|
|
559
|
-
scrollContainerRef.current?.scrollTo({ top: 0 });
|
|
560
|
-
}, []);
|
|
561
|
-
const commitScroll = useCallback((top, left) => {
|
|
562
564
|
const scrollContainer = scrollContainerRef.current;
|
|
563
565
|
if (!scrollContainer)
|
|
564
566
|
return;
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
latestScrollRef.current = { top, left };
|
|
570
|
-
latestCommittedScrollRef.current = { top, left };
|
|
571
|
-
setScroll(top, left);
|
|
572
|
-
}, [setScroll]);
|
|
567
|
+
const nextTop = type === 'all' || type === 'top' ? 0 : latestScrollRef.current.top;
|
|
568
|
+
const nextLeft = type === 'all' || type === 'left' ? 0 : scrollContainer.scrollLeft;
|
|
569
|
+
commitScroll(nextTop, nextLeft);
|
|
570
|
+
}, [commitScroll]);
|
|
573
571
|
useEffect(() => {
|
|
574
572
|
if (!searchOpen || activeSearchMatchIndex === undefined)
|
|
575
573
|
return;
|
|
@@ -593,6 +591,7 @@ function Table(props) {
|
|
|
593
591
|
frozenRowCount,
|
|
594
592
|
columns,
|
|
595
593
|
rowHeight: trHeight,
|
|
594
|
+
verticalScrollState: logicalVerticalScrollState,
|
|
596
595
|
viewportInsets,
|
|
597
596
|
});
|
|
598
597
|
if (result.didScroll)
|
|
@@ -602,6 +601,7 @@ function Table(props) {
|
|
|
602
601
|
columns,
|
|
603
602
|
commitScroll,
|
|
604
603
|
frozenRowCount,
|
|
604
|
+
logicalVerticalScrollState,
|
|
605
605
|
props.frozenColumnIndex,
|
|
606
606
|
searchMatches,
|
|
607
607
|
searchOpen,
|
|
@@ -833,18 +833,18 @@ function Table(props) {
|
|
|
833
833
|
if (!dragState || !pointer || !scrollContainer || !bodyContainer)
|
|
834
834
|
return;
|
|
835
835
|
const delta = getSelectionAutoScrollDelta(pointer.clientX, pointer.clientY, bodyContainer, scrollContainer);
|
|
836
|
-
const maxScrollTop =
|
|
836
|
+
const maxScrollTop = virtualScrollWindowMetrics.logicalMaxScroll;
|
|
837
837
|
const maxScrollLeft = Math.max(scrollContainer.scrollWidth - scrollContainer.clientWidth, 0);
|
|
838
|
-
const nextScrollTop = clamp(
|
|
838
|
+
const nextScrollTop = clamp(latestScrollRef.current.top + delta.y, 0, maxScrollTop);
|
|
839
839
|
const nextScrollLeft = clamp(scrollContainer.scrollLeft + delta.x, 0, maxScrollLeft);
|
|
840
|
-
if (nextScrollTop !==
|
|
840
|
+
if (nextScrollTop !== latestScrollRef.current.top || nextScrollLeft !== scrollContainer.scrollLeft) {
|
|
841
841
|
commitScroll(nextScrollTop, nextScrollLeft);
|
|
842
842
|
}
|
|
843
843
|
updateSelectionByPointer(pointer.clientX, pointer.clientY);
|
|
844
844
|
if (cellSelectionDragRef.current && (delta.x !== 0 || delta.y !== 0)) {
|
|
845
845
|
selectionAutoScrollRafRef.current = requestAnimationFrame(runSelectionAutoScroll);
|
|
846
846
|
}
|
|
847
|
-
}, [commitScroll, updateSelectionByPointer]);
|
|
847
|
+
}, [commitScroll, updateSelectionByPointer, virtualScrollWindowMetrics.logicalMaxScroll]);
|
|
848
848
|
const selectAllCells = useCallback(() => {
|
|
849
849
|
if (!cellSelectionEnabled)
|
|
850
850
|
return false;
|
|
@@ -1499,8 +1499,6 @@ function Table(props) {
|
|
|
1499
1499
|
if (scrollContainerRefCurrent) {
|
|
1500
1500
|
scrollContainerRefCurrent.removeEventListener('scroll', onScroll);
|
|
1501
1501
|
scrollContainerRefCurrent.addEventListener('scroll', onScroll, { passive: true, capture: true });
|
|
1502
|
-
// scrollContainerRefCurrent.removeEventListener('wheel', onWheel);
|
|
1503
|
-
// scrollContainerRefCurrent.addEventListener('wheel', onWheel, { passive: false, capture: true });
|
|
1504
1502
|
}
|
|
1505
1503
|
return () => {
|
|
1506
1504
|
if (scrollRafRef.current !== null) {
|
|
@@ -1514,18 +1512,16 @@ function Table(props) {
|
|
|
1514
1512
|
containerRefCurrent?.removeAttribute('data-bgrid-scrolling');
|
|
1515
1513
|
scrollContainerRefCurrent?.removeEventListener('scroll', onScroll);
|
|
1516
1514
|
};
|
|
1517
|
-
}, [onScroll,
|
|
1515
|
+
}, [onScroll, setInitialized]);
|
|
1518
1516
|
React.useLayoutEffect(() => {
|
|
1519
1517
|
if (!scrollContainerRef.current)
|
|
1520
1518
|
return;
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
scrollContainerRef.current.scrollTop = props.scrollTop;
|
|
1526
|
-
}
|
|
1527
|
-
}, [props.scrollLeft, props.scrollTop]);
|
|
1519
|
+
const nextTop = props.scrollTop ?? latestScrollRef.current.top;
|
|
1520
|
+
const nextLeft = props.scrollLeft ?? latestScrollRef.current.left;
|
|
1521
|
+
commitScroll(nextTop, nextLeft);
|
|
1522
|
+
}, [commitScroll, props.scrollLeft, props.scrollTop]);
|
|
1528
1523
|
useEffect(() => {
|
|
1524
|
+
latestScrollRef.current = { top: scrollTop, left: scrollLeft };
|
|
1529
1525
|
latestCommittedScrollRef.current = { top: scrollTop, left: scrollLeft };
|
|
1530
1526
|
}, [scrollTop, scrollLeft]);
|
|
1531
1527
|
useEffect(() => {
|
|
@@ -1606,6 +1602,7 @@ function Table(props) {
|
|
|
1606
1602
|
searchOpen,
|
|
1607
1603
|
searchOptions,
|
|
1608
1604
|
trHeight,
|
|
1605
|
+
verticalScrollState: logicalVerticalScrollState,
|
|
1609
1606
|
viewportInsets: keyboardViewportInsets,
|
|
1610
1607
|
});
|
|
1611
1608
|
keyboardRuntimeRef.current = {
|
|
@@ -1638,6 +1635,7 @@ function Table(props) {
|
|
|
1638
1635
|
searchOpen,
|
|
1639
1636
|
searchOptions,
|
|
1640
1637
|
trHeight,
|
|
1638
|
+
verticalScrollState: logicalVerticalScrollState,
|
|
1641
1639
|
viewportInsets: keyboardViewportInsets,
|
|
1642
1640
|
};
|
|
1643
1641
|
useEffect(() => {
|
|
@@ -1653,7 +1651,7 @@ function Table(props) {
|
|
|
1653
1651
|
}
|
|
1654
1652
|
};
|
|
1655
1653
|
const moveWithArrowKey = (key, extendSelection, toBoundary = false) => {
|
|
1656
|
-
const { activeCell, cellInteractionSession, cellNavigationOptions, cellSelectionEnabled, columns, commitScroll, dataLength, frozenColumnIndex, frozenRowCount, moveActiveCell, trHeight, viewportInsets, } = keyboardRuntimeRef.current;
|
|
1654
|
+
const { activeCell, cellInteractionSession, cellNavigationOptions, cellSelectionEnabled, columns, commitScroll, dataLength, frozenColumnIndex, frozenRowCount, moveActiveCell, trHeight, verticalScrollState, viewportInsets, } = keyboardRuntimeRef.current;
|
|
1657
1655
|
const container = containerRef.current;
|
|
1658
1656
|
const activeElement = document.activeElement;
|
|
1659
1657
|
if (!container ||
|
|
@@ -1687,6 +1685,7 @@ function Table(props) {
|
|
|
1687
1685
|
frozenRowCount,
|
|
1688
1686
|
columns,
|
|
1689
1687
|
rowHeight: trHeight,
|
|
1688
|
+
verticalScrollState,
|
|
1690
1689
|
viewportInsets,
|
|
1691
1690
|
});
|
|
1692
1691
|
if (result.didScroll) {
|
|
@@ -1718,7 +1717,7 @@ function Table(props) {
|
|
|
1718
1717
|
arrowRepeatFrame = requestAnimationFrame(runArrowRepeatFrame);
|
|
1719
1718
|
};
|
|
1720
1719
|
const handleKeyDown = (evt) => {
|
|
1721
|
-
const { activeCell, cellInteractionSession, cellNavigationOptions, cellSelectionEnabled, clearCellSelection, clearCellSelectionOnEscape, columns, commitCheckboxCell, commitScroll, copySelectedCells, data, dataLength, editable, editItemIndex, endCellSelectionDrag, frozenColumnIndex, frozenRowCount, height, handleClick, moveActiveCell, openCellContextMenu, selectAllCells, setEditItem, requestSearchOpen, searchOpen, searchOptions, trHeight, viewportInsets, } = keyboardRuntimeRef.current;
|
|
1720
|
+
const { activeCell, cellInteractionSession, cellNavigationOptions, cellSelectionEnabled, clearCellSelection, clearCellSelectionOnEscape, columns, commitCheckboxCell, commitScroll, copySelectedCells, data, dataLength, editable, editItemIndex, endCellSelectionDrag, frozenColumnIndex, frozenRowCount, height, handleClick, moveActiveCell, openCellContextMenu, selectAllCells, setEditItem, requestSearchOpen, searchOpen, searchOptions, trHeight, verticalScrollState, viewportInsets, } = keyboardRuntimeRef.current;
|
|
1722
1721
|
const container = containerRef.current;
|
|
1723
1722
|
const activeElement = document.activeElement;
|
|
1724
1723
|
if (!container || (activeElement !== container && !container.contains(activeElement)))
|
|
@@ -1846,6 +1845,7 @@ function Table(props) {
|
|
|
1846
1845
|
frozenRowCount,
|
|
1847
1846
|
columns,
|
|
1848
1847
|
rowHeight: trHeight,
|
|
1848
|
+
verticalScrollState,
|
|
1849
1849
|
viewportInsets,
|
|
1850
1850
|
});
|
|
1851
1851
|
if (result.didScroll) {
|
|
@@ -1889,6 +1889,7 @@ function Table(props) {
|
|
|
1889
1889
|
frozenRowCount,
|
|
1890
1890
|
columns,
|
|
1891
1891
|
rowHeight: trHeight,
|
|
1892
|
+
verticalScrollState,
|
|
1892
1893
|
viewportInsets,
|
|
1893
1894
|
});
|
|
1894
1895
|
if (result.didScroll) {
|
|
@@ -1916,6 +1917,7 @@ function Table(props) {
|
|
|
1916
1917
|
frozenRowCount,
|
|
1917
1918
|
columns,
|
|
1918
1919
|
rowHeight: trHeight,
|
|
1920
|
+
verticalScrollState,
|
|
1919
1921
|
viewportInsets,
|
|
1920
1922
|
});
|
|
1921
1923
|
if (result.didScroll) {
|
|
@@ -2022,7 +2024,7 @@ function Table(props) {
|
|
|
2022
2024
|
event.stopPropagation();
|
|
2023
2025
|
}
|
|
2024
2026
|
} },
|
|
2025
|
-
React.createElement(ScrollPlane, { style: { height: scrollPlaneHeight, minWidth: scrollPlaneMinWidth } },
|
|
2027
|
+
React.createElement(ScrollPlane, { style: { height: scrollPlaneHeight, minWidth: scrollPlaneMinWidth }, "data-bgrid-virtual-scroll-window": virtualScrollWindowMetrics.enabled ? 'true' : undefined, "data-bgrid-logical-height": virtualScrollWindowMetrics.logicalContentHeight, "data-bgrid-physical-height": virtualScrollWindowMetrics.physicalContentHeight, "data-bgrid-logical-scroll-top": Math.round(scrollTop), "data-bgrid-virtual-scroll-base": virtualScrollWindowMetrics.enabled ? Math.round(virtualScrollBase) : undefined },
|
|
2026
2028
|
React.createElement(HeaderContainer, { style: { height: headerHeight, top: 0 }, role: 'rfdg-header-container' },
|
|
2027
2029
|
(frozenColumnsWidth ?? 0) > 0 && (React.createElement(FrozenHeader, { style: { width: frozenColumnsWidth }, role: 'rfdg-frozen-header' },
|
|
2028
2030
|
React.createElement(TableHeadFrozen, { container: containerRef }))),
|
|
@@ -2033,7 +2035,7 @@ function Table(props) {
|
|
|
2033
2035
|
React.createElement(TableSummaryFrozen, { position: 'top' }))),
|
|
2034
2036
|
React.createElement(Summary, { style: { left: frozenColumnsWidth }, role: 'rfdg-summary' },
|
|
2035
2037
|
React.createElement(TableSummary, { position: 'top' })))),
|
|
2036
|
-
React.createElement("div", { className: 'bgrid-body-scroll-content', style: { height:
|
|
2038
|
+
React.createElement("div", { className: 'bgrid-body-scroll-content', style: { height: virtualScrollWindowMetrics.physicalContentHeight } },
|
|
2037
2039
|
frozenRowCount > 0 && (React.createElement("div", { className: 'bgrid-frozen-rows-layer', style: { height: frozenRowsHeight, top: stickyTopHeight }, "data-bgrid-row-band": 'frozen' },
|
|
2038
2040
|
(frozenColumnsWidth ?? 0) > 0 && (React.createElement("div", { className: 'bgrid-frozen-rows-left bgrid-frozen-column-boundary', style: { width: frozenColumnsWidth }, role: 'rfdg-frozen-rows-left' },
|
|
2039
2041
|
React.createElement(TableBodyFrozen, { scrollContainerRef: scrollContainerRef, rowRange: frozenRowRange, role: 'rfdg-body-top-frozen', quadrant: 'top-left', allowRowReorder: false }),
|
|
@@ -2041,17 +2043,19 @@ function Table(props) {
|
|
|
2041
2043
|
React.createElement("div", { className: 'bgrid-frozen-rows-main', style: { left: frozenColumnsWidth }, role: 'rfdg-frozen-rows-main' },
|
|
2042
2044
|
React.createElement(TableBody, { scrollContainerRef: scrollContainerRef, rowRange: frozenRowRange, role: 'rfdg-body-top', quadrant: 'top-main', allowRowReorder: false }),
|
|
2043
2045
|
renderSelectionOverlay('top-main')))),
|
|
2044
|
-
React.createElement("div", { className: 'bgrid-scrollable-rows-layer', style: { height:
|
|
2046
|
+
React.createElement("div", { className: 'bgrid-scrollable-rows-layer', style: { height: physicalScrollableRowsHeight }, "data-bgrid-row-band": 'scrollable' },
|
|
2045
2047
|
(frozenColumnsWidth ?? 0) > 0 && (React.createElement(FrozenScrollContent, { style: {
|
|
2046
2048
|
width: frozenColumnsWidth,
|
|
2047
|
-
height:
|
|
2049
|
+
height: physicalScrollableRowsHeight,
|
|
2048
2050
|
}, role: 'rfdg-frozen-scroll-container' },
|
|
2049
2051
|
React.createElement(TableBodyFrozen, { scrollContainerRef: scrollContainerRef, rowRange: scrollableRowRange, style: frozenScrollableBodyStyle, quadrant: 'body-left', onRowReorderPointerDown: rowReorderController.onPointerDown, onRowReorderKeyDown: rowReorderController.onKeyDown }),
|
|
2050
2052
|
renderSelectionOverlay('body-left'))),
|
|
2051
2053
|
React.createElement(ScrollContent, { style: {
|
|
2052
2054
|
left: frozenColumnsWidth,
|
|
2053
|
-
paddingTop:
|
|
2054
|
-
|
|
2055
|
+
paddingTop: virtualScrollWindowMetrics.enabled
|
|
2056
|
+
? visibleScrollableRows.paddingTop - virtualScrollBase
|
|
2057
|
+
: visibleScrollableRows.paddingTop,
|
|
2058
|
+
height: physicalScrollableRowsHeight,
|
|
2055
2059
|
} },
|
|
2056
2060
|
React.createElement(TableBody, { scrollContainerRef: scrollContainerRef, rowRange: scrollableRowRange, quadrant: 'body-main' }),
|
|
2057
2061
|
renderSelectionOverlay('body-main')))),
|
|
@@ -2141,7 +2145,7 @@ function getCellPositionFromPointer({ clientX, clientY, bodyContainer, scrollCon
|
|
|
2141
2145
|
const rowIndex = metrics.frozenRowCount > 0 && clientY < frozenRowsBottom
|
|
2142
2146
|
? clamp(Math.floor((clientY - bodyRect.top) / metrics.trHeight), 0, metrics.frozenRowCount - 1)
|
|
2143
2147
|
: clamp(metrics.frozenRowCount +
|
|
2144
|
-
Math.floor((
|
|
2148
|
+
Math.floor((metrics.scrollTop +
|
|
2145
2149
|
clamp(clientY - scrollRect.top, 0, Math.max(scrollContainer.clientHeight - 1, 0))) /
|
|
2146
2150
|
metrics.trHeight), 0, metrics.dataLength - 1);
|
|
2147
2151
|
const columnIndex = getColumnIndexFromPointer({
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { clipCellSelectionFragment, } from '../../utils/cellSelectionGeometry';
|
|
3
|
-
export function CellSelectionOverlayLayer({ quadrant, selectionFragments, activeFragments, activeFill, activeRing, viewport, }) {
|
|
3
|
+
export function CellSelectionOverlayLayer({ quadrant, selectionFragments, activeFragments, activeFill, activeRing, viewport, offsetTop = 0, }) {
|
|
4
4
|
const quadrantSelectionFragments = getVisibleFragments(selectionFragments, quadrant, viewport);
|
|
5
5
|
const quadrantActiveFragments = getVisibleFragments(activeFragments, quadrant, viewport);
|
|
6
6
|
if (quadrantSelectionFragments.length === 0 && quadrantActiveFragments.length === 0)
|
|
7
7
|
return null;
|
|
8
8
|
return (React.createElement("div", { className: 'bgrid-cell-selection-overlay-layer', "data-bgrid-selection-quadrant": quadrant, "aria-hidden": 'true' },
|
|
9
|
-
quadrantSelectionFragments.map(fragment => (React.createElement("div", { key: `selection-${fragment.rangeIndex}`, className: 'bgrid-cell-selection-fragment', "data-bgrid-selection-fragment": 'true', "data-bgrid-selection-range-index": fragment.rangeIndex, "data-edge-top": fragment.edges.top ? 'true' : undefined, "data-edge-right": fragment.edges.right ? 'true' : undefined, "data-edge-bottom": fragment.edges.bottom ? 'true' : undefined, "data-edge-left": fragment.edges.left ? 'true' : undefined, style: getFragmentStyle(fragment) }))),
|
|
9
|
+
quadrantSelectionFragments.map(fragment => (React.createElement("div", { key: `selection-${fragment.rangeIndex}`, className: 'bgrid-cell-selection-fragment', "data-bgrid-selection-fragment": 'true', "data-bgrid-selection-range-index": fragment.rangeIndex, "data-edge-top": fragment.edges.top ? 'true' : undefined, "data-edge-right": fragment.edges.right ? 'true' : undefined, "data-edge-bottom": fragment.edges.bottom ? 'true' : undefined, "data-edge-left": fragment.edges.left ? 'true' : undefined, style: getFragmentStyle(fragment, offsetTop) }))),
|
|
10
10
|
(activeFill || activeRing) &&
|
|
11
|
-
quadrantActiveFragments.map(fragment => (React.createElement("div", { key: `active-${fragment.rangeIndex}`, className: 'bgrid-cell-active-fragment', "data-bgrid-active-fragment": 'true', "data-active-fill": activeFill ? 'true' : undefined, "data-active-ring": activeRing ? 'true' : undefined, style: getFragmentStyle(fragment) })))));
|
|
11
|
+
quadrantActiveFragments.map(fragment => (React.createElement("div", { key: `active-${fragment.rangeIndex}`, className: 'bgrid-cell-active-fragment', "data-bgrid-active-fragment": 'true', "data-active-fill": activeFill ? 'true' : undefined, "data-active-ring": activeRing ? 'true' : undefined, style: getFragmentStyle(fragment, offsetTop) })))));
|
|
12
12
|
}
|
|
13
13
|
function getVisibleFragments(fragments, quadrant, viewport) {
|
|
14
14
|
return fragments.flatMap(fragment => {
|
|
@@ -18,10 +18,10 @@ function getVisibleFragments(fragments, quadrant, viewport) {
|
|
|
18
18
|
return visibleFragment ? [visibleFragment] : [];
|
|
19
19
|
});
|
|
20
20
|
}
|
|
21
|
-
function getFragmentStyle(fragment) {
|
|
21
|
+
function getFragmentStyle(fragment, offsetTop) {
|
|
22
22
|
return {
|
|
23
23
|
left: fragment.left,
|
|
24
|
-
top: fragment.top,
|
|
24
|
+
top: fragment.top - offsetTop,
|
|
25
25
|
width: fragment.width,
|
|
26
26
|
height: fragment.height,
|
|
27
27
|
};
|
package/esm/utils/coordinate.js
CHANGED
|
@@ -41,8 +41,8 @@ export function getRowBottom(rowIndex, rowHeight) {
|
|
|
41
41
|
return 0;
|
|
42
42
|
return (rowIndex + 1) * rowHeight;
|
|
43
43
|
}
|
|
44
|
-
export function ensureCellVisible({ cell, scrollContainer, frozenColumnCount = 0, frozenRowCount = 0, columns, rowHeight, viewportInsets, }) {
|
|
45
|
-
const currentScrollTop = scrollContainer?.scrollTop ?? 0;
|
|
44
|
+
export function ensureCellVisible({ cell, scrollContainer, frozenColumnCount = 0, frozenRowCount = 0, columns, rowHeight, verticalScrollState, viewportInsets, }) {
|
|
45
|
+
const currentScrollTop = verticalScrollState?.scrollTop ?? scrollContainer?.scrollTop ?? 0;
|
|
46
46
|
const currentScrollLeft = scrollContainer?.scrollLeft ?? 0;
|
|
47
47
|
let nextScrollTop = currentScrollTop;
|
|
48
48
|
let nextScrollLeft = currentScrollLeft;
|
|
@@ -52,7 +52,7 @@ export function ensureCellVisible({ cell, scrollContainer, frozenColumnCount = 0
|
|
|
52
52
|
const rowTop = getRowTop(targetRowIndex, rowHeight);
|
|
53
53
|
const rowBottom = getRowBottom(targetRowIndex, rowHeight);
|
|
54
54
|
const clientHeight = scrollContainer.clientHeight;
|
|
55
|
-
const scrollHeight = scrollContainer.scrollHeight;
|
|
55
|
+
const scrollHeight = verticalScrollState?.scrollHeight ?? scrollContainer.scrollHeight;
|
|
56
56
|
const maxScrollTop = Math.max(0, scrollHeight - clientHeight);
|
|
57
57
|
if (clientHeight > 0) {
|
|
58
58
|
const topInset = clamp(viewportInsets?.top ?? 0, 0, clientHeight);
|
|
@@ -95,7 +95,7 @@ export function ensureCellVisible({ cell, scrollContainer, frozenColumnCount = 0
|
|
|
95
95
|
const didScrollLeft = nextScrollLeft !== currentScrollLeft;
|
|
96
96
|
const didScroll = didScrollTop || didScrollLeft;
|
|
97
97
|
if (scrollContainer) {
|
|
98
|
-
if (didScrollTop) {
|
|
98
|
+
if (didScrollTop && !verticalScrollState) {
|
|
99
99
|
scrollContainer.scrollTop = nextScrollTop;
|
|
100
100
|
}
|
|
101
101
|
if (didScrollLeft) {
|
package/esm/utils/index.js
CHANGED
|
@@ -15,6 +15,7 @@ export * from './scrollbar';
|
|
|
15
15
|
export * from './number';
|
|
16
16
|
export * from './buildHeaderMatrix';
|
|
17
17
|
export * from './getVisibleScrollableRowRange';
|
|
18
|
+
export * from './virtualScrollWindow';
|
|
18
19
|
export * from './cellEditState';
|
|
19
20
|
export * from './getCellSelectionAxisState';
|
|
20
21
|
export * from './mergedCells';
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export const BGRID_MAX_PHYSICAL_SCROLL_HEIGHT = 1000000;
|
|
2
|
+
export function getVirtualScrollWindowMetrics({ logicalContentHeight, viewportHeight, enabled, maxPhysicalHeight = BGRID_MAX_PHYSICAL_SCROLL_HEIGHT, }) {
|
|
3
|
+
const safeViewportHeight = Math.max(viewportHeight, 0);
|
|
4
|
+
const safeLogicalContentHeight = Math.max(logicalContentHeight, safeViewportHeight);
|
|
5
|
+
const safeMaxPhysicalHeight = Math.max(maxPhysicalHeight, safeViewportHeight);
|
|
6
|
+
const windowingEnabled = enabled && safeLogicalContentHeight > safeMaxPhysicalHeight;
|
|
7
|
+
const physicalContentHeight = windowingEnabled ? safeMaxPhysicalHeight : safeLogicalContentHeight;
|
|
8
|
+
return {
|
|
9
|
+
enabled: windowingEnabled,
|
|
10
|
+
logicalContentHeight: safeLogicalContentHeight,
|
|
11
|
+
physicalContentHeight,
|
|
12
|
+
logicalMaxScroll: Math.max(safeLogicalContentHeight - safeViewportHeight, 0),
|
|
13
|
+
physicalMaxScroll: Math.max(physicalContentHeight - safeViewportHeight, 0),
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export function getLogicalScrollTop(base, physicalScrollTop, metrics) {
|
|
17
|
+
return clamp(base + physicalScrollTop, 0, metrics.logicalMaxScroll);
|
|
18
|
+
}
|
|
19
|
+
export function getVirtualScrollWindowPosition(logicalScrollTop, metrics) {
|
|
20
|
+
const logicalTop = clamp(logicalScrollTop, 0, metrics.logicalMaxScroll);
|
|
21
|
+
if (!metrics.enabled) {
|
|
22
|
+
return {
|
|
23
|
+
base: 0,
|
|
24
|
+
physicalScrollTop: logicalTop,
|
|
25
|
+
logicalScrollTop: logicalTop,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
const preferredPhysicalTop = metrics.physicalMaxScroll / 2;
|
|
29
|
+
const maxBase = Math.max(metrics.logicalMaxScroll - metrics.physicalMaxScroll, 0);
|
|
30
|
+
const base = clamp(logicalTop - preferredPhysicalTop, 0, maxBase);
|
|
31
|
+
return {
|
|
32
|
+
base,
|
|
33
|
+
physicalScrollTop: logicalTop - base,
|
|
34
|
+
logicalScrollTop: logicalTop,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
export function rebaseVirtualScrollWindow(base, physicalScrollTop, metrics) {
|
|
38
|
+
const logicalScrollTop = getLogicalScrollTop(base, physicalScrollTop, metrics);
|
|
39
|
+
if (!metrics.enabled || metrics.physicalMaxScroll <= 0) {
|
|
40
|
+
return getVirtualScrollWindowPosition(logicalScrollTop, metrics);
|
|
41
|
+
}
|
|
42
|
+
const lowerGuard = metrics.physicalMaxScroll * 0.25;
|
|
43
|
+
const upperGuard = metrics.physicalMaxScroll * 0.75;
|
|
44
|
+
const maxBase = Math.max(metrics.logicalMaxScroll - metrics.physicalMaxScroll, 0);
|
|
45
|
+
const canMoveBackward = base > 0;
|
|
46
|
+
const canMoveForward = base < maxBase;
|
|
47
|
+
if ((physicalScrollTop < lowerGuard && canMoveBackward) ||
|
|
48
|
+
(physicalScrollTop > upperGuard && canMoveForward)) {
|
|
49
|
+
return getVirtualScrollWindowPosition(logicalScrollTop, metrics);
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
base,
|
|
53
|
+
physicalScrollTop: clamp(physicalScrollTop, 0, metrics.physicalMaxScroll),
|
|
54
|
+
logicalScrollTop,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function clamp(value, min, max) {
|
|
58
|
+
return Math.min(Math.max(value, min), max);
|
|
59
|
+
}
|
package/package.json
CHANGED
|
@@ -13,6 +13,7 @@ interface Props {
|
|
|
13
13
|
activeFill: boolean;
|
|
14
14
|
activeRing: boolean;
|
|
15
15
|
viewport: SelectionViewport;
|
|
16
|
+
offsetTop?: number;
|
|
16
17
|
}
|
|
17
|
-
export declare function CellSelectionOverlayLayer({ quadrant, selectionFragments, activeFragments, activeFill, activeRing, viewport, }: Props): React.JSX.Element | null;
|
|
18
|
+
export declare function CellSelectionOverlayLayer({ quadrant, selectionFragments, activeFragments, activeFill, activeRing, viewport, offsetTop, }: Props): React.JSX.Element | null;
|
|
18
19
|
export {};
|
|
@@ -12,6 +12,10 @@ export interface EnsureCellVisibleParams {
|
|
|
12
12
|
frozenRowCount?: number;
|
|
13
13
|
columns: AppModelColumn<any>[];
|
|
14
14
|
rowHeight: number;
|
|
15
|
+
verticalScrollState?: {
|
|
16
|
+
scrollTop: number;
|
|
17
|
+
scrollHeight: number;
|
|
18
|
+
};
|
|
15
19
|
viewportInsets?: {
|
|
16
20
|
top?: number;
|
|
17
21
|
right?: number;
|
|
@@ -26,4 +30,4 @@ export interface EnsureCellVisibleResult {
|
|
|
26
30
|
didScrollTop: boolean;
|
|
27
31
|
didScrollLeft: boolean;
|
|
28
32
|
}
|
|
29
|
-
export declare function ensureCellVisible({ cell, scrollContainer, frozenColumnCount, frozenRowCount, columns, rowHeight, viewportInsets, }: EnsureCellVisibleParams): EnsureCellVisibleResult;
|
|
33
|
+
export declare function ensureCellVisible({ cell, scrollContainer, frozenColumnCount, frozenRowCount, columns, rowHeight, verticalScrollState, viewportInsets, }: EnsureCellVisibleParams): EnsureCellVisibleResult;
|
package/types/utils/index.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export * from './scrollbar';
|
|
|
15
15
|
export * from './number';
|
|
16
16
|
export * from './buildHeaderMatrix';
|
|
17
17
|
export * from './getVisibleScrollableRowRange';
|
|
18
|
+
export * from './virtualScrollWindow';
|
|
18
19
|
export * from './cellEditState';
|
|
19
20
|
export * from './getCellSelectionAxisState';
|
|
20
21
|
export * from './mergedCells';
|