From e3d2e8aeef64be7b3e2ad94aca78a6d10d936058 Mon Sep 17 00:00:00 2001 From: Li <25043398+qili26@users.noreply.github.com> Date: Thu, 2 Jan 2020 13:20:17 -0600 Subject: [PATCH 1/2] feat: extend the onScroll api --- examples/demos/example13-all-features.tsx | 36 +++++++++++++++++++++-- examples/index.html | 18 ++++++++++++ src/Canvas.tsx | 4 +-- src/DataGrid.tsx | 6 ++-- style/rdg-core.less | 1 + 5 files changed, 58 insertions(+), 7 deletions(-) diff --git a/examples/demos/example13-all-features.tsx b/examples/demos/example13-all-features.tsx index c2cc93e635..2c7f0687a5 100644 --- a/examples/demos/example13-all-features.tsx +++ b/examples/demos/example13-all-features.tsx @@ -1,7 +1,8 @@ import faker from 'faker'; -import React, { useState, useMemo, useCallback, useRef } from 'react'; +import React, { useCallback, useMemo, useRef, useState } from 'react'; import { AutoSizer } from 'react-virtualized'; -import DataGrid, { Column, CellContent, SelectColumn, UpdateActions, DataGridHandle, GridRowsUpdatedEvent } from '../../src'; + +import DataGrid, { CellContent, Column, DataGridHandle, GridRowsUpdatedEvent, ScrollPosition, SelectColumn, UpdateActions } from '../../src'; import DropDownEditor from './components/Editors/DropDownEditor'; import ImageFormatter from './components/Formatters/ImageFormatter'; import Toolbar from './components/Toolbar/Toolbar'; @@ -28,6 +29,11 @@ faker.locale = 'en_GB'; const titles = ['Dr.', 'Mr.', 'Mrs.', 'Miss', 'Ms.']; +function isReachedBottom(event: React.UIEvent): boolean { + const target = event.target as HTMLDivElement; + return target.clientHeight + target.scrollTop === target.scrollHeight; +} + function createFakeRowObjectData(index: number): Row { return { id: `id_${index}`, @@ -47,6 +53,18 @@ function createFakeRowObjectData(index: number): Row { }; } +function loadMoreRows(newRowsCount: number, length: number): Promise { + return new Promise(resolve => { + const newRows: Row[] = []; + + for (let i = 0; i < newRowsCount; i++) { + newRows[i] = createFakeRowObjectData(i + length); + } + + setTimeout(() => resolve(newRows), 1500); + }); +} + function createRows(numberOfRows: number): Row[] { const rows: Row[] = []; @@ -60,6 +78,7 @@ function createRows(numberOfRows: number): Row[] { export default function AllFeaturesExample(): JSX.Element { const [rows, setRows] = useState(() => createRows(2000)); const [selectedRows, setSelectedRows] = useState(() => new Set()); + const [isLoading, setIsLoading] = useState(false); const gridRef = useRef(null); const columns: Column[] = useMemo(() => [ @@ -191,6 +210,17 @@ export default function AllFeaturesExample(): JSX.Element { const handleAddRow = useCallback(({ newRowIndex }: { newRowIndex: number}): void => setRows([...rows, createFakeRowObjectData(newRowIndex)]), [rows]); + const handleScroll = useCallback(async (position: ScrollPosition, event: React.UIEvent) => { + if (!isReachedBottom(event)) return; + + setIsLoading(true); + + const newRows = await loadMoreRows(50, rows.length); + + setRows([...rows, ...newRows]); + setIsLoading(false); + }, [rows]); + const getRowAt = useCallback((index: number): Row => rows[index], [rows]); const getSize = useCallback((): number => rows.length, [rows.length]); @@ -200,6 +230,7 @@ export default function AllFeaturesExample(): JSX.Element { return ( <> + { isLoading &&
Loading new rows...
}
@@ -218,6 +249,7 @@ export default function AllFeaturesExample(): JSX.Element { onSelectedRowsChange={onSelectedRowsChange} enableCellCopyPaste enableCellDragAndDrop + onScroll={handleScroll} /> )} diff --git a/examples/index.html b/examples/index.html index 78b4400ec5..090942bd56 100644 --- a/examples/index.html +++ b/examples/index.html @@ -125,6 +125,24 @@ .rdg-cell.rdg-cell-action { overflow: visible; } + + .rdg-loading { + position: fixed; + width: 100%; + height: 100%; + z-index: 5; + text-align: center; + background-color: rgba(0,0,0,0.8); + } + + .rdg-loading .rdg-loading-text { + transform: translate(-50%, -50%); + top: 50%; + left: 50%; + position: absolute; + color: white; + font-size: 24px; + } diff --git a/src/Canvas.tsx b/src/Canvas.tsx index 542c1050e2..2c99076132 100644 --- a/src/Canvas.tsx +++ b/src/Canvas.tsx @@ -51,7 +51,7 @@ export interface CanvasProps extends SharedDataGridProps): void; onCanvasKeydown?(e: React.KeyboardEvent): void; onCanvasKeyup?(e: React.KeyboardEvent): void; onRowSelectionChange(rowIdx: number, row: R, checked: boolean, isShiftClick: boolean): void; @@ -102,7 +102,7 @@ function Canvas({ function handleScroll(e: React.UIEvent) { const { scrollLeft, scrollTop } = e.currentTarget; setScrollTop(scrollTop); - onScroll({ scrollLeft, scrollTop }); + onScroll({ scrollLeft, scrollTop }, e); if (summaryRef.current) { summaryRef.current.scrollLeft = scrollLeft; } diff --git a/src/DataGrid.tsx b/src/DataGrid.tsx index 308ed3de61..83e73f432d 100644 --- a/src/DataGrid.tsx +++ b/src/DataGrid.tsx @@ -108,7 +108,7 @@ export interface DataGridProps { /** Function called whenever grid is sorted*/ onGridSort?(columnKey: keyof R, direction: DEFINE_SORT): void; /** Called when the grid is scrolled */ - onScroll?(scrollPosition: ScrollPosition): void; + onScroll?(scrollPosition: ScrollPosition, event: React.UIEvent): void; /** Component used to render a draggable header cell */ draggableHeaderCell?: React.ComponentType<{ column: CalculatedColumn; onHeaderDrop(): void }>; RowsContainer?: React.ComponentType; @@ -240,12 +240,12 @@ function DataGrid({ props.onColumnResize?.(column.idx, width); } - function handleScroll(scrollPosition: ScrollPosition) { + function handleScroll(scrollPosition: ScrollPosition, event: React.UIEvent) { if (headerRef.current) { headerRef.current.scrollLeft = scrollPosition.scrollLeft; } setScrollLeft(scrollPosition.scrollLeft); - props.onScroll?.(scrollPosition); + props.onScroll?.(scrollPosition, event); } function handleGridRowsUpdated(event: GridRowsUpdatedEvent) { diff --git a/style/rdg-core.less b/style/rdg-core.less index 9644bba62f..a1a2a5f57f 100644 --- a/style/rdg-core.less +++ b/style/rdg-core.less @@ -29,4 +29,5 @@ .rdg-grid { // min-height is here to show the horizontal scrollbar when there are no rows min-height: 1px; + margin-bottom: 8px; } From 044944e47aa328d7344898b9932fff60f36628fa Mon Sep 17 00:00:00 2001 From: Li <25043398+qili26@users.noreply.github.com> Date: Thu, 2 Jan 2020 13:40:14 -0600 Subject: [PATCH 2/2] chores: tweak loading style --- examples/demos/Wrapper.tsx | 23 ++++++---- examples/demos/example13-all-features.tsx | 53 +++++++++++------------ examples/index.html | 5 +-- 3 files changed, 42 insertions(+), 39 deletions(-) diff --git a/examples/demos/Wrapper.tsx b/examples/demos/Wrapper.tsx index 7db006bc58..08992b9a5b 100644 --- a/examples/demos/Wrapper.tsx +++ b/examples/demos/Wrapper.tsx @@ -3,10 +3,10 @@ import { Menu, MenuOpen } from '@material-ui/icons'; interface Props { title: string; - children: React.ReactChild; + isLoading?: boolean; } -export default function Wrapper({ title, children }: Props) { +export default function Wrapper({ title, children, isLoading }: React.PropsWithChildren) { const [isSidebarVisible, setIsSidebarVisible] = useState(true); useLayoutEffect(() => { @@ -17,11 +17,18 @@ export default function Wrapper({ title, children }: Props) { }, [isSidebarVisible]); return ( -
-

setIsSidebarVisible(!isSidebarVisible)}> - {isSidebarVisible ? : } {title} -

- {children} -
+ <> + {isLoading && ( +
+
Loading...
+
+ )} +
+

setIsSidebarVisible(!isSidebarVisible)}> + {isSidebarVisible ? : } {title} +

+ {children} +
+ ); } diff --git a/examples/demos/example13-all-features.tsx b/examples/demos/example13-all-features.tsx index 2c7f0687a5..d771038654 100644 --- a/examples/demos/example13-all-features.tsx +++ b/examples/demos/example13-all-features.tsx @@ -61,7 +61,7 @@ function loadMoreRows(newRowsCount: number, length: number): Promise { newRows[i] = createFakeRowObjectData(i + length); } - setTimeout(() => resolve(newRows), 1500); + setTimeout(() => resolve(newRows), 1000); }); } @@ -228,33 +228,30 @@ export default function AllFeaturesExample(): JSX.Element { const onSelectedRowsChange = useCallback((newSelectedRows: Set): void => setSelectedRows(newSelectedRows), []); return ( - - <> - { isLoading &&
Loading new rows...
} - -
- - {({ height, width }) => ( - - ref={gridRef} - enableCellSelect - columns={columns} - rowGetter={getRowAt} - rowsCount={getSize()} - onGridRowsUpdated={handleGridRowsUpdated} - rowHeight={30} - minWidth={width} - minHeight={height} - selectedRows={selectedRows} - onSelectedRowsChange={onSelectedRowsChange} - enableCellCopyPaste - enableCellDragAndDrop - onScroll={handleScroll} - /> - )} - -
- + + +
+ + {({ height, width }) => ( + + ref={gridRef} + enableCellSelect + columns={columns} + rowGetter={getRowAt} + rowsCount={getSize()} + onGridRowsUpdated={handleGridRowsUpdated} + rowHeight={30} + minWidth={width} + minHeight={height} + selectedRows={selectedRows} + onSelectedRowsChange={onSelectedRowsChange} + enableCellCopyPaste + enableCellDragAndDrop + onScroll={handleScroll} + /> + )} + +
); } diff --git a/examples/index.html b/examples/index.html index 090942bd56..fd3484b16d 100644 --- a/examples/index.html +++ b/examples/index.html @@ -130,9 +130,8 @@ position: fixed; width: 100%; height: 100%; - z-index: 5; - text-align: center; - background-color: rgba(0,0,0,0.8); + z-index: 9999; + background-color: rgba(0,0,0,0.75); } .rdg-loading .rdg-loading-text {