diff --git a/vuu-ui/packages/vuu-table/src/Table.css b/vuu-ui/packages/vuu-table/src/Table.css index 899af4e02e..89db988dfc 100644 --- a/vuu-ui/packages/vuu-table/src/Table.css +++ b/vuu-ui/packages/vuu-table/src/Table.css @@ -45,9 +45,10 @@ position: absolute; top: var(--total-header-height); width: var(--table-width); -} +} + .vuuTable-scrollbarContainer::-webkit-scrollbar { border: none; width: 10px; diff --git a/vuu-ui/packages/vuu-table/src/table-cell/TableCell.tsx b/vuu-ui/packages/vuu-table/src/table-cell/TableCell.tsx index 7f61a7740d..daaa681ff9 100644 --- a/vuu-ui/packages/vuu-table/src/table-cell/TableCell.tsx +++ b/vuu-ui/packages/vuu-table/src/table-cell/TableCell.tsx @@ -1,6 +1,6 @@ import { DataItemCommitHandler, TableCellProps } from "@finos/vuu-table-types"; import { isNumericColumn } from "@finos/vuu-utils"; -import { MouseEventHandler, useCallback, useEffect } from "react"; +import { MouseEventHandler, useCallback } from "react"; import { useCell } from "../useCell"; import "./TableCell.css"; diff --git a/vuu-ui/packages/vuu-table/src/useKeyboardNavigation.ts b/vuu-ui/packages/vuu-table/src/useKeyboardNavigation.ts index 570ae2c901..cd0aa50949 100644 --- a/vuu-ui/packages/vuu-table/src/useKeyboardNavigation.ts +++ b/vuu-ui/packages/vuu-table/src/useKeyboardNavigation.ts @@ -301,9 +301,9 @@ NavigationHookProps) => { break; } } - setTimeout(() => { + requestAnimationFrame(() => { resolve([newRowIdx, colIdx]); - }, 90); + }); }), [requestScroll, rowCount, viewportRowCount] ); diff --git a/vuu-ui/packages/vuu-table/src/useTableScroll.ts b/vuu-ui/packages/vuu-table/src/useTableScroll.ts index 7817cbb29b..4637ab16b2 100644 --- a/vuu-ui/packages/vuu-table/src/useTableScroll.ts +++ b/vuu-ui/packages/vuu-table/src/useTableScroll.ts @@ -56,7 +56,19 @@ const getMaxScroll = (container: HTMLElement) => { return [scrollWidth - clientWidth, scrollHeight - clientHeight]; }; -const getPctScroll = (container: HTMLElement, approximateBoundaries = true) => { +const getScrollDirection = ( + prevScrollPositions: ScrollPos | undefined, + scrollPos: number +) => { + if (prevScrollPositions === undefined) { + return undefined; + } else { + const { scrollTop: prevTop } = prevScrollPositions; + return scrollPos > prevTop ? "fwd" : "bwd"; + } +}; + +const getPctScroll = (container: HTMLElement, currentScrollPos?: ScrollPos) => { const { clientHeight, clientWidth, @@ -69,16 +81,24 @@ const getPctScroll = (container: HTMLElement, approximateBoundaries = true) => { const maxScrollLeft = scrollWidth - clientWidth; const pctScrollLeft = scrollLeft / (scrollWidth - clientWidth); const maxScrollTop = scrollHeight - clientHeight; - const pctScrollTop = scrollTop / (scrollHeight - clientHeight); + let pctScrollTop = scrollTop / (scrollHeight - clientHeight); - if (approximateBoundaries) { - if (pctScrollTop > 0.99) { - return [pctScrollLeft, 1]; - } else if (pctScrollTop < 0.02) { - return [pctScrollLeft, 0]; - } + const scrollDirection = getScrollDirection(currentScrollPos, scrollTop); + + if (scrollDirection === "fwd" && pctScrollTop > 0.99) { + pctScrollTop = 1; + } else if (scrollDirection === "bwd" && pctScrollTop < 0.02) { + pctScrollTop = 0; } - return [pctScrollLeft, pctScrollTop, maxScrollLeft, maxScrollTop]; + + return [ + scrollLeft, + pctScrollLeft, + maxScrollLeft, + scrollTop, + pctScrollTop, + maxScrollTop, + ]; }; export const noScrolling: ScrollingAPI = { @@ -113,6 +133,11 @@ const useCallbackRef = ({ return callbackRef; }; +type ScrollPos = { + scrollLeft: number; + scrollTop: number; +}; + export interface TableScrollHookProps { getRowAtPosition: RowAtPositionFunc; onHorizontalScroll?: (scrollLeft: number) => void; @@ -140,8 +165,15 @@ export const useTableScroll = ({ }: TableScrollHookProps) => { const firstRowRef = useRef(0); const contentContainerScrolledRef = useRef(false); + const contentContainerPosRef = useRef({ + scrollTop: 0, + scrollLeft: 0, + }); const scrollbarContainerScrolledRef = useRef(false); - const scrollPosRef = useRef({ scrollTop: 0, scrollLeft: 0 }); + const scrollbarContainerPosRef = useRef({ + scrollTop: 0, + scrollLeft: 0, + }); const scrollbarContainerRef = useRef(null); const contentContainerRef = useRef(null); @@ -168,18 +200,19 @@ export const useTableScroll = ({ const { current: contentContainer } = contentContainerRef; const { current: scrollbarContainer } = scrollbarContainerRef; const { current: contentContainerScrolled } = contentContainerScrolledRef; - const { current: scrollPos } = scrollPosRef; + const { current: scrollPos } = scrollbarContainerPosRef; + if (contentContainerScrolled) { contentContainerScrolledRef.current = false; } else if (contentContainer && scrollbarContainer) { scrollbarContainerScrolledRef.current = true; - const [maxScrollLeft, maxScrollTop] = getMaxScroll(contentContainer); - const approximateBoundaries = - scrollPos.scrollTop > 0 && scrollPos.scrollTop < maxScrollTop; - const [pctScrollLeft, pctScrollTop] = getPctScroll( - scrollbarContainer, - approximateBoundaries - ); + const [scrollLeft, pctScrollLeft, , scrollTop, pctScrollTop] = + getPctScroll(scrollbarContainer, scrollPos); + + scrollPos.scrollLeft = scrollLeft; + scrollPos.scrollTop = scrollTop; + + const [maxScrollLeft, maxScrollTop] = getMaxScroll(scrollbarContainer); const contentScrollLeft = Math.round(pctScrollLeft * maxScrollLeft); const contentScrollTop = pctScrollTop * maxScrollTop; @@ -197,12 +230,17 @@ export const useTableScroll = ({ scrollbarContainerScrolledRef; const { current: contentContainer } = contentContainerRef; const { current: scrollbarContainer } = scrollbarContainerRef; - const { current: scrollPos } = scrollPosRef; + const { current: scrollPos } = contentContainerPosRef; if (contentContainer && scrollbarContainer) { - const { scrollLeft, scrollTop } = contentContainer; - const [pctScrollLeft, pctScrollTop, maxScrollLeft, maxScrollTop] = - getPctScroll(contentContainer); + const [ + scrollLeft, + pctScrollLeft, + maxScrollLeft, + scrollTop, + pctScrollTop, + maxScrollTop, + ] = getPctScroll(contentContainer); contentContainerScrolledRef.current = true; diff --git a/vuu-ui/packages/vuu-table/src/useTableViewport.ts b/vuu-ui/packages/vuu-table/src/useTableViewport.ts index c81dabf8a1..e993a71a75 100644 --- a/vuu-ui/packages/vuu-table/src/useTableViewport.ts +++ b/vuu-ui/packages/vuu-table/src/useTableViewport.ts @@ -46,7 +46,7 @@ export interface TableViewportHookResult extends ViewportMeasurements { } // Too simplistic, it depends on rowHeight -const MAX_RAW_ROWS = 1_000_000; +const MAX_PIXEL_HEIGHT = 10_000_000; const UNMEASURED_VIEWPORT: TableViewportHookResult = { appliedPageSize: 0, @@ -77,7 +77,7 @@ export const useTableViewport = ({ const inSituRowOffsetRef = useRef(0); const pctScrollTopRef = useRef(0); // TODO we are limited by pixels not an arbitraty number of rows - const pixelContentHeight = rowHeight * Math.min(rowCount, MAX_RAW_ROWS); + const pixelContentHeight = Math.min(rowHeight * rowCount, MAX_PIXEL_HEIGHT); const virtualContentHeight = rowCount * rowHeight; const virtualisedExtent = virtualContentHeight - pixelContentHeight;