Introduce range finder

Summary: Show a hint during scrolling of the relative offset the user is looking at. This is based on the current virtualisation window, so not 100% accurate, but probably still provides the right signal to the user. See the bottom right of the recording

Reviewed By: nikoant

Differential Revision: D26450261

fbshipit-source-id: 206a860024e346c6b872edc3fc7919019046a6d7
This commit is contained in:
Michel Weststrate
2021-03-16 14:54:53 -07:00
committed by Facebook GitHub Bot
parent 1ce665ceaf
commit 8aabce477b
3 changed files with 67 additions and 29 deletions

View File

@@ -91,8 +91,8 @@ export class DataSource<
private dataUpdateQueue: DataEvent<T>[] = [];
private windowStart = 0;
private windowEnd = 0;
windowStart = 0;
windowEnd = 0;
private outputChangeListener?: (change: OutputChange) => void;

View File

@@ -55,6 +55,7 @@ type DataSourceProps<T extends object, C> = {
defaultRowHeight: number;
onKeyDown?: React.KeyboardEventHandler<HTMLDivElement>;
virtualizerRef?: MutableRefObject<DataSourceVirtualizer | undefined>;
onRangeChange?(start: number, end: number, total: number): void;
_testHeight?: number; // exposed for unit testing only
};
@@ -73,6 +74,7 @@ export const DataSourceRenderer: <T extends object, C>(
autoScroll,
onKeyDown,
virtualizerRef,
onRangeChange,
_testHeight,
}: DataSourceProps<any, any>) {
/**
@@ -176,6 +178,9 @@ export const DataSourceRenderer: <T extends object, C>(
useLayoutEffect(function updateWindow() {
const start = virtualizer.virtualItems[0]?.index ?? 0;
const end = start + virtualizer.virtualItems.length;
if (start !== dataSource.windowStart && !followOutput.current) {
onRangeChange?.(start, end, dataSource.output.length);
}
dataSource.setWindow(start, end);
});

View File

@@ -12,6 +12,7 @@ import React, {
useLayoutEffect,
useMemo,
useRef,
useState,
RefObject,
MutableRefObject,
} from 'react';
@@ -23,6 +24,8 @@ import {Percentage} from '../utils/widthUtils';
import {DataSourceRenderer, DataSourceVirtualizer} from './DataSourceRenderer';
import {useDataTableManager, TableManager} from './useDataTableManager';
import {TableSearch} from './TableSearch';
import styled from '@emotion/styled';
import {theme} from '../theme';
interface DataTableProps<T = any> {
columns: DataTableColumn<T>[];
@@ -161,34 +164,64 @@ export function DataTable<T extends object>(props: DataTableProps<T>) {
[selection],
);
/** Range finder */
const [range, setRange] = useState('');
const hideRange = useRef<NodeJS.Timeout>();
const onRangeChange = useCallback(
(start: number, end: number, total: number) => {
// TODO: figure out if we don't trigger this callback to often hurting perf
setRange(`${start} - ${end} / ${total}`);
clearTimeout(hideRange.current!);
hideRange.current = setTimeout(() => {
setRange('');
}, 1000);
},
[],
);
return (
<Layout.Top>
<Layout.Container>
<TableSearch
onSearch={tableManager.setSearchValue}
extraActions={props.extraActions}
<Layout.Container grow>
<Layout.Top>
<Layout.Container>
<TableSearch
onSearch={tableManager.setSearchValue}
extraActions={props.extraActions}
/>
<TableHead
columns={tableManager.columns}
visibleColumns={tableManager.visibleColumns}
onColumnResize={tableManager.resizeColumn}
onReset={tableManager.reset}
onColumnToggleVisibility={tableManager.toggleColumnVisibility}
sorting={tableManager.sorting}
onColumnSort={tableManager.sortColumn}
/>
</Layout.Container>
<DataSourceRenderer<T, RenderContext<T>>
dataSource={dataSource}
autoScroll={props.autoScroll}
useFixedRowHeight={!usesWrapping}
defaultRowHeight={DEFAULT_ROW_HEIGHT}
context={renderingConfig}
itemRenderer={itemRenderer}
onKeyDown={onKeyDown}
virtualizerRef={virtualizerRef}
onRangeChange={onRangeChange}
_testHeight={props._testHeight}
/>
<TableHead
columns={tableManager.columns}
visibleColumns={tableManager.visibleColumns}
onColumnResize={tableManager.resizeColumn}
onReset={tableManager.reset}
onColumnToggleVisibility={tableManager.toggleColumnVisibility}
sorting={tableManager.sorting}
onColumnSort={tableManager.sortColumn}
/>
</Layout.Container>
<DataSourceRenderer<T, RenderContext<T>>
dataSource={dataSource}
autoScroll={props.autoScroll}
useFixedRowHeight={!usesWrapping}
defaultRowHeight={DEFAULT_ROW_HEIGHT}
context={renderingConfig}
itemRenderer={itemRenderer}
onKeyDown={onKeyDown}
virtualizerRef={virtualizerRef}
_testHeight={props._testHeight}
/>
</Layout.Top>
</Layout.Top>
{range && <RangeFinder>{range}</RangeFinder>}
</Layout.Container>
);
}
const RangeFinder = styled.div({
backgroundColor: theme.backgroundWash,
position: 'absolute',
right: 40,
bottom: 20,
padding: '4px 8px',
color: theme.textColorSecondary,
fontSize: '0.8em',
});