-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathindex.tsx
59 lines (55 loc) · 2.07 KB
/
index.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import { Pagination, VStack } from '@navikt/ds-react';
import { chunk } from 'lodash';
import { type ComponentProps, type ComponentPropsWithRef, type JSX, useEffect, useMemo, useState } from 'react';
type Props<T, KeyType> = Omit<ComponentPropsWithRef<typeof VStack>, 'as'> & {
items: T[];
pageSize?: number;
renderItem: ({ item }: { item: T }) => JSX.Element;
keyExtractor: (item: T) => KeyType;
selectedKey?: KeyType;
as?: ComponentPropsWithRef<typeof VStack>['as'];
paginationSrHeading?: ComponentProps<typeof Pagination>['srHeading'];
};
export const PaginatedList = <T, KeyType extends string | number>({
items,
pageSize = 10,
renderItem: RenderComp,
keyExtractor,
selectedKey,
as,
paginationSrHeading,
...rest
}: Props<T, KeyType>) => {
const [page, setPage] = useState(0);
const pages = useMemo(() => chunk(items, pageSize), [items, pageSize]);
const pageCount = useMemo(() => pages.length, [pages]);
const renderItems = useMemo(() => pages[page > pageCount - 1 ? pageCount - 1 : page], [pages, page, pageCount]);
useEffect(() => {
if (selectedKey) {
const pageWithItem = pages.findIndex((p) => p.map(keyExtractor).includes(selectedKey));
if (pageWithItem >= 0) {
setPage(pageWithItem);
return;
}
}
setPage(0);
}, [selectedKey, pages, keyExtractor]);
return (
<VStack as={as ?? 'div'} gap="2" justify="space-between" flexGrow="1" minHeight="0" {...rest}>
<VStack gap="2" paddingInline="0 2" overflowY="scroll">
{renderItems?.map((item) => (
<RenderComp item={item} key={keyExtractor(item)} />
))}
</VStack>
<Pagination
srHeading={paginationSrHeading}
size="small"
page={page + 1}
siblingCount={0}
count={pageCount}
onPageChange={(page) => setPage(page - 1)}
prevNextTexts={false}
/>
</VStack>
);
};