// // Copyright 2023 DXOS.org // import { type Meta } from '@storybook/react-vite'; import { useVirtualizer } from '@tanstack/react-virtual'; import React, { useEffect, useMemo, useRef, useState } from 'react'; import { random } from '@dxos/random'; import { Panel, ScrollArea, Toolbar } from '@dxos/react-ui'; import { withLayout, withTheme } from '@dxos/react-ui/testing'; random.seed(999); type TestItem = { name: string; }; const meta: Meta = { title: 'ui/react-ui-core/exemplars/virtualizer', decorators: [withLayout({ layout: 'column' }), withTheme()], parameters: { layout: 'fullscreen', }, }; export default meta; const NUM_ITEMS = 500; /** * https://tanstack.com/virtual/latest/docs/introduction */ export const Default = { render: () => { const [index, setIndex] = useState(0); const items = useMemo( () => Array.from({ length: NUM_ITEMS }, () => ({ name: random.lorem.paragraph(), })), [], ); const parentRef = useRef(null); const [viewport, setViewport] = useState(null); const virtualizer = useVirtualizer({ getScrollElement: () => viewport, estimateSize: () => 40, count: items.length, gap: 8, }); useEffect(() => { virtualizer.scrollToIndex(index, { align: 'start' }); }, [virtualizer, index]); const virtualItems = virtualizer.getVirtualItems(); return (
{virtualItems.map((virtualItem) => (
{virtualItem.index + 1}
{items[virtualItem.index].name}
))}
); }, }; const ScrollToolbar = ({ items, index, setIndex, }: { items: any[]; index: number; setIndex: (index: number) => void; }) => { return (
setIndex(0)} /> setIndex(Math.floor(Math.random() * items.length))} /> setIndex(items.length - 1)} />
{index + 1}/{items.length}
); };