Skip to content

Commit

Permalink
Add infinite scrolling example (#2637)
Browse files Browse the repository at this point in the history
* Add InfiniteScrolling example

* Update stories/demos/InfiniteScrolling.tsx

Co-authored-by: Nicolas Stepien <[email protected]>

* Update stories/demos/InfiniteScrolling.tsx

Co-authored-by: Nicolas Stepien <[email protected]>

Co-authored-by: Nicolas Stepien <[email protected]>
  • Loading branch information
amanmahajan7 and nstepien authored Sep 8, 2021
1 parent af0848a commit e3ddda4
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 64 deletions.
83 changes: 19 additions & 64 deletions stories/demos/AllFeatures.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,6 @@ const highlightClassname = css`
}
`;

const loadMoreRowsClassname = css`
width: 180px;
padding: 8px 16px;
position: absolute;
bottom: 8px;
right: 8px;
color: white;
line-height: 35px;
background: rgba(0, 0, 0, 0.6);
`;

export interface Row {
id: string;
avatar: string;
Expand Down Expand Up @@ -155,55 +144,34 @@ const columns: readonly Column<Row>[] = [
}
];

function createFakeRowObjectData(index: number): Row {
return {
id: `id_${index}`,
avatar: faker.image.avatar(),
email: faker.internet.email(),
title: faker.name.prefix(),
firstName: faker.name.firstName(),
lastName: faker.name.lastName(),
street: faker.address.streetName(),
zipCode: faker.address.zipCode(),
date: faker.date.past().toLocaleDateString(),
bs: faker.company.bs(),
catchPhrase: faker.company.catchPhrase(),
companyName: faker.company.companyName(),
words: faker.lorem.words(),
sentence: faker.lorem.sentence()
};
}

function createRows(numberOfRows: number): Row[] {
function createRows(): Row[] {
const rows: Row[] = [];

for (let i = 0; i < numberOfRows; i++) {
rows[i] = createFakeRowObjectData(i);
for (let i = 0; i < 2000; i++) {
rows.push({
id: `id_${i}`,
avatar: faker.image.avatar(),
email: faker.internet.email(),
title: faker.name.prefix(),
firstName: faker.name.firstName(),
lastName: faker.name.lastName(),
street: faker.address.streetName(),
zipCode: faker.address.zipCode(),
date: faker.date.past().toLocaleDateString(),
bs: faker.company.bs(),
catchPhrase: faker.company.catchPhrase(),
companyName: faker.company.companyName(),
words: faker.lorem.words(),
sentence: faker.lorem.sentence()
});
}

return rows;
}

function isAtBottom({ currentTarget }: React.UIEvent<HTMLDivElement>): boolean {
return currentTarget.clientHeight + currentTarget.scrollTop === currentTarget.scrollHeight;
}

function loadMoreRows(newRowsCount: number, length: number): Promise<Row[]> {
return new Promise((resolve) => {
const newRows: Row[] = [];

for (let i = 0; i < newRowsCount; i++) {
newRows[i] = createFakeRowObjectData(i + length);
}

setTimeout(() => resolve(newRows), 1000);
});
}

export function AllFeatures() {
const [rows, setRows] = useState(() => createRows(2000));
const [rows, setRows] = useState(createRows);
const [selectedRows, setSelectedRows] = useState<ReadonlySet<string>>(() => new Set());
const [isLoading, setIsLoading] = useState(false);

function handleFill({ columnKey, sourceRow, targetRow }: FillEvent<Row>): Row {
return { ...targetRow, [columnKey]: sourceRow[columnKey as keyof Row] };
Expand All @@ -229,17 +197,6 @@ export function AllFeatures() {
return { ...targetRow, [targetColumnKey]: sourceRow[sourceColumnKey as keyof Row] };
}

async function handleScroll(event: React.UIEvent<HTMLDivElement>) {
if (!isAtBottom(event)) return;

setIsLoading(true);

const newRows = await loadMoreRows(50, rows.length);

setRows([...rows, ...newRows]);
setIsLoading(false);
}

return (
<>
<DataGrid
Expand All @@ -251,12 +208,10 @@ export function AllFeatures() {
onPaste={handlePaste}
rowHeight={30}
selectedRows={selectedRows}
onScroll={handleScroll}
onSelectedRowsChange={setSelectedRows}
className="fill-grid"
rowClass={(row) => (row.id.includes('7') ? highlightClassname : undefined)}
/>
{isLoading && <div className={loadMoreRowsClassname}>Loading more rows...</div>}
</>
);
}
Expand Down
120 changes: 120 additions & 0 deletions stories/demos/InfiniteScrolling.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import faker from 'faker';
import { useState } from 'react';
import { css } from '@linaria/core';
import DataGrid from '../../src';
import type { Column } from '../../src';

const loadMoreRowsClassname = css`
width: 180px;
padding: 8px 16px;
position: absolute;
bottom: 8px;
right: 8px;
color: white;
line-height: 35px;
background: rgb(0 0 0 / 0.6);
`;

interface Row {
id: string;
email: string;
title: string;
firstName: string;
lastName: string;
}

function rowKeyGetter(row: Row) {
return row.id;
}

const columns: readonly Column<Row>[] = [
{
key: 'id',
name: 'ID'
},
{
key: 'title',
name: 'Title'
},
{
key: 'firstName',
name: 'First Name'
},
{
key: 'lastName',
name: 'Last Name'
},
{
key: 'email',
name: 'Email'
}
];

function createFakeRowObjectData(index: number): Row {
return {
id: `id_${index}`,
email: faker.internet.email(),
title: faker.name.prefix(),
firstName: faker.name.firstName(),
lastName: faker.name.lastName()
};
}

function createRows(numberOfRows: number): Row[] {
const rows: Row[] = [];

for (let i = 0; i < numberOfRows; i++) {
rows[i] = createFakeRowObjectData(i);
}

return rows;
}

function isAtBottom({ currentTarget }: React.UIEvent<HTMLDivElement>): boolean {
return currentTarget.scrollTop + 10 >= currentTarget.scrollHeight - currentTarget.clientHeight;
}

function loadMoreRows(newRowsCount: number, length: number): Promise<Row[]> {
return new Promise((resolve) => {
const newRows: Row[] = [];

for (let i = 0; i < newRowsCount; i++) {
newRows[i] = createFakeRowObjectData(i + length);
}

setTimeout(() => resolve(newRows), 1000);
});
}

export function InfiniteScrolling() {
const [rows, setRows] = useState(() => createRows(50));
const [isLoading, setIsLoading] = useState(false);

async function handleScroll(event: React.UIEvent<HTMLDivElement>) {
if (isLoading || !isAtBottom(event)) return;

setIsLoading(true);

const newRows = await loadMoreRows(50, rows.length);

setRows([...rows, ...newRows]);
setIsLoading(false);
}

return (
<>
<DataGrid
columns={columns}
rows={rows}
rowKeyGetter={rowKeyGetter}
onRowsChange={setRows}
rowHeight={30}
onScroll={handleScroll}
className="fill-grid"
/>
{isLoading && <div className={loadMoreRowsClassname}>Loading more rows...</div>}
</>
);
}

InfiniteScrolling.storyName = 'Infinite Scrolling';
1 change: 1 addition & 0 deletions stories/index.story.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ export * from './demos/Grouping';
export * from './demos/Resizable';
export * from './demos/VariableRowHeight';
export * from './demos/MasterDetail';
export * from './demos/InfiniteScrolling';

export default { title: 'Demos' };

0 comments on commit e3ddda4

Please sign in to comment.