diff --git a/stories/demos/AllFeatures.tsx b/stories/demos/AllFeatures.tsx index dad7b47abb..2c8dd76246 100644 --- a/stories/demos/AllFeatures.tsx +++ b/stories/demos/AllFeatures.tsx @@ -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; @@ -155,55 +144,34 @@ const columns: readonly Column[] = [ } ]; -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): boolean { - return currentTarget.clientHeight + currentTarget.scrollTop === currentTarget.scrollHeight; -} - -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), 1000); - }); -} - export function AllFeatures() { - const [rows, setRows] = useState(() => createRows(2000)); + const [rows, setRows] = useState(createRows); const [selectedRows, setSelectedRows] = useState>(() => new Set()); - const [isLoading, setIsLoading] = useState(false); function handleFill({ columnKey, sourceRow, targetRow }: FillEvent): Row { return { ...targetRow, [columnKey]: sourceRow[columnKey as keyof Row] }; @@ -229,17 +197,6 @@ export function AllFeatures() { return { ...targetRow, [targetColumnKey]: sourceRow[sourceColumnKey as keyof Row] }; } - async function handleScroll(event: React.UIEvent) { - if (!isAtBottom(event)) return; - - setIsLoading(true); - - const newRows = await loadMoreRows(50, rows.length); - - setRows([...rows, ...newRows]); - setIsLoading(false); - } - return ( <> (row.id.includes('7') ? highlightClassname : undefined)} /> - {isLoading &&
Loading more rows...
} ); } diff --git a/stories/demos/InfiniteScrolling.tsx b/stories/demos/InfiniteScrolling.tsx new file mode 100644 index 0000000000..38efa73bb2 --- /dev/null +++ b/stories/demos/InfiniteScrolling.tsx @@ -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[] = [ + { + 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): boolean { + return currentTarget.scrollTop + 10 >= currentTarget.scrollHeight - currentTarget.clientHeight; +} + +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), 1000); + }); +} + +export function InfiniteScrolling() { + const [rows, setRows] = useState(() => createRows(50)); + const [isLoading, setIsLoading] = useState(false); + + async function handleScroll(event: React.UIEvent) { + if (isLoading || !isAtBottom(event)) return; + + setIsLoading(true); + + const newRows = await loadMoreRows(50, rows.length); + + setRows([...rows, ...newRows]); + setIsLoading(false); + } + + return ( + <> + + {isLoading &&
Loading more rows...
} + + ); +} + +InfiniteScrolling.storyName = 'Infinite Scrolling'; diff --git a/stories/index.story.ts b/stories/index.story.ts index 90d82f75e2..652353a013 100644 --- a/stories/index.story.ts +++ b/stories/index.story.ts @@ -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' };