mirror of
https://github.com/nextui-org/nextui.git
synced 2025-12-08 19:26:11 +00:00
fix(docs): table async pagination (#1491)
* fix(docs): change to swr * chore(table): change to swr * fix(table): keep the pagination when switching pages * chore(repo): pnpm lockfile updated
This commit is contained in:
parent
64571e468c
commit
d8d2b87cb8
@ -11,8 +11,8 @@ import {
|
|||||||
Spinner,
|
Spinner,
|
||||||
Pagination,
|
Pagination,
|
||||||
} from "@nextui-org/react";
|
} from "@nextui-org/react";
|
||||||
import {useAsyncList} from "@react-stately/data";
|
import {useMemo, useState} from "react";
|
||||||
import {useCallback, useMemo, useState} from "react";
|
import useSWR from "swr";
|
||||||
|
|
||||||
type SWCharacter = {
|
type SWCharacter = {
|
||||||
name: string;
|
name: string;
|
||||||
@ -21,50 +21,23 @@ type SWCharacter = {
|
|||||||
birth_year: string;
|
birth_year: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const fetcher = (...args: Parameters<typeof fetch>) => fetch(...args).then((res) => res.json());
|
||||||
|
|
||||||
export default function Page() {
|
export default function Page() {
|
||||||
const [page, setPage] = useState(1);
|
const [page, setPage] = useState(1);
|
||||||
const [total, setTotal] = useState(0);
|
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const {data, isLoading} = useSWR<{
|
||||||
|
count: number;
|
||||||
|
results: SWCharacter[];
|
||||||
|
}>(`https://swapi.py4e.com/api/people?page=${page}`, fetcher, {
|
||||||
|
keepPreviousData: true,
|
||||||
|
});
|
||||||
|
|
||||||
const rowsPerPage = 10;
|
const rowsPerPage = 10;
|
||||||
|
|
||||||
let list = useAsyncList<SWCharacter>({
|
const pages = useMemo(() => {
|
||||||
async load({signal, cursor}) {
|
return data?.count ? Math.ceil(data.count / rowsPerPage) : 0;
|
||||||
// If no cursor is available, then we're loading the first page.
|
}, [data?.count, rowsPerPage]);
|
||||||
// Otherwise, the cursor is the next URL to load, as returned from the previous page.
|
|
||||||
const res = await fetch(cursor || "https://swapi.py4e.com/api/people/?search=", {signal});
|
|
||||||
let json = await res.json();
|
|
||||||
|
|
||||||
setTotal(json.count);
|
|
||||||
|
|
||||||
setIsLoading(false);
|
|
||||||
|
|
||||||
return {
|
|
||||||
items: json.results,
|
|
||||||
cursor: json.next,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const pages = Math.ceil(total / rowsPerPage);
|
|
||||||
|
|
||||||
const items = useMemo(() => {
|
|
||||||
const start = (page - 1) * rowsPerPage;
|
|
||||||
const end = start + rowsPerPage;
|
|
||||||
|
|
||||||
return list.items.slice(start, end);
|
|
||||||
}, [page, list.items?.length]);
|
|
||||||
|
|
||||||
const onPaginationChange = useCallback(
|
|
||||||
(page: number) => {
|
|
||||||
setIsLoading(true);
|
|
||||||
if (page >= list.items.length / rowsPerPage) {
|
|
||||||
list.loadMore();
|
|
||||||
}
|
|
||||||
setPage(page);
|
|
||||||
},
|
|
||||||
[list.items.length],
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="p-6">
|
<div className="p-6">
|
||||||
@ -80,7 +53,7 @@ export default function Page() {
|
|||||||
color="primary"
|
color="primary"
|
||||||
page={page}
|
page={page}
|
||||||
total={pages}
|
total={pages}
|
||||||
onChange={onPaginationChange}
|
onChange={(page) => setPage(page)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : null
|
) : null
|
||||||
@ -96,8 +69,8 @@ export default function Page() {
|
|||||||
<TableColumn key="birth_year">Birth year</TableColumn>
|
<TableColumn key="birth_year">Birth year</TableColumn>
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
<TableBody
|
<TableBody
|
||||||
isLoading={isLoading && !items.length}
|
isLoading={isLoading || data?.results.length === 0}
|
||||||
items={items}
|
items={data?.results ?? []}
|
||||||
loadingContent={<Spinner />}
|
loadingContent={<Spinner />}
|
||||||
>
|
>
|
||||||
{(item) => (
|
{(item) => (
|
||||||
|
|||||||
@ -256,7 +256,7 @@ const users = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
type User = (typeof users)[0];
|
type User = typeof users[0];
|
||||||
|
|
||||||
export default function Page() {
|
export default function Page() {
|
||||||
const [filterValue, setFilterValue] = useState("");
|
const [filterValue, setFilterValue] = useState("");
|
||||||
|
|||||||
@ -256,7 +256,7 @@ const users = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
type User = (typeof users)[0];
|
type User = typeof users[0];
|
||||||
|
|
||||||
export default function Page() {
|
export default function Page() {
|
||||||
const [filterValue, setFilterValue] = useState("");
|
const [filterValue, setFilterValue] = useState("");
|
||||||
|
|||||||
@ -108,9 +108,9 @@ function CodeTypewriter({value, className, css, ...props}: any) {
|
|||||||
return (
|
return (
|
||||||
<Pre className={className} css={css} {...props}>
|
<Pre className={className} css={css} {...props}>
|
||||||
<code
|
<code
|
||||||
dangerouslySetInnerHTML={{__html: value}}
|
|
||||||
ref={wrapperRef}
|
ref={wrapperRef}
|
||||||
className={className}
|
className={className}
|
||||||
|
dangerouslySetInnerHTML={{__html: value}}
|
||||||
style={{opacity: 0}}
|
style={{opacity: 0}}
|
||||||
/>
|
/>
|
||||||
</Pre>
|
</Pre>
|
||||||
@ -155,7 +155,7 @@ const CodeBlock = React.forwardRef<HTMLPreElement, CodeBlockProps>((_props, forw
|
|||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{showWindowIcons && <WindowActions title={title} />}
|
{showWindowIcons && <WindowActions title={title} />}
|
||||||
<code dangerouslySetInnerHTML={{__html: result}} className={clsx(classes, codeClasses)} />
|
<code className={clsx(classes, codeClasses)} dangerouslySetInnerHTML={{__html: result}} />
|
||||||
</Pre>
|
</Pre>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,50 +1,22 @@
|
|||||||
const App = `import {Table, TableHeader, TableColumn, TableBody, TableRow, TableCell, Pagination, Spinner, getKeyValue} from "@nextui-org/react";
|
const App = `import {Table, TableHeader, TableColumn, TableBody, TableRow, TableCell, Pagination, Spinner, getKeyValue} from "@nextui-org/react";
|
||||||
import {useAsyncList} from "@react-stately/data";
|
import useSWR from "swr";
|
||||||
|
|
||||||
|
const fetcher = (...args) => fetch(...args).then((res) => res.json());
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const [page, setPage] = React.useState(1);
|
const [page, setPage] = React.useState(1);
|
||||||
const [total, setTotal] = React.useState(0);
|
|
||||||
const [isLoading, setIsLoading] = React.useState(true);
|
const {data, isLoading} = useSWR(\`https://swapi.py4e.com/api/people?page=\$\{page\}\`, fetcher, {
|
||||||
|
keepPreviousData: true,
|
||||||
|
});
|
||||||
|
|
||||||
const rowsPerPage = 10;
|
const rowsPerPage = 10;
|
||||||
|
|
||||||
let list = useAsyncList({
|
const pages = useMemo(() => {
|
||||||
async load({signal, cursor}) {
|
return data?.count ? Math.ceil(data.count / rowsPerPage) : 0;
|
||||||
// If no cursor is available, then we're loading the first page.
|
}, [data?.count, rowsPerPage]);
|
||||||
// Otherwise, the cursor is the next URL to load, as returned from the previous page.
|
|
||||||
const res = await fetch(cursor || "https://swapi.py4e.com/api/people/?search=", {signal});
|
|
||||||
let json = await res.json();
|
|
||||||
|
|
||||||
setTotal(json.count);
|
const loadingState = isLoading || data?.results.length === 0 ? "loading" : "idle";
|
||||||
|
|
||||||
setIsLoading(false);
|
|
||||||
|
|
||||||
return {
|
|
||||||
items: json.results,
|
|
||||||
cursor: json.next,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const pages = Math.ceil(total / rowsPerPage);
|
|
||||||
|
|
||||||
const items = React.useMemo(() => {
|
|
||||||
const start = (page - 1) * rowsPerPage;
|
|
||||||
const end = start + rowsPerPage;
|
|
||||||
|
|
||||||
return list.items.slice(start, end);
|
|
||||||
}, [page, list.items?.length]);
|
|
||||||
|
|
||||||
const onPaginationChange = React.useCallback(
|
|
||||||
(page) => {
|
|
||||||
setIsLoading(true);
|
|
||||||
if (page >= list.items.length / rowsPerPage) {
|
|
||||||
list.loadMore();
|
|
||||||
}
|
|
||||||
setPage(page);
|
|
||||||
},
|
|
||||||
[list.items.length],
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Table
|
<Table
|
||||||
@ -59,14 +31,12 @@ export default function App() {
|
|||||||
color="primary"
|
color="primary"
|
||||||
page={page}
|
page={page}
|
||||||
total={pages}
|
total={pages}
|
||||||
onChange={onPaginationChange}
|
onChange={(page) => setPage(page)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : null
|
) : null
|
||||||
}
|
}
|
||||||
classNames={{
|
{...args}
|
||||||
table: "min-h-[400px]",
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<TableHeader>
|
<TableHeader>
|
||||||
<TableColumn key="name">Name</TableColumn>
|
<TableColumn key="name">Name</TableColumn>
|
||||||
@ -75,12 +45,12 @@ export default function App() {
|
|||||||
<TableColumn key="birth_year">Birth year</TableColumn>
|
<TableColumn key="birth_year">Birth year</TableColumn>
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
<TableBody
|
<TableBody
|
||||||
isLoading={isLoading && !items.length}
|
items={data?.results ?? []}
|
||||||
items={items}
|
|
||||||
loadingContent={<Spinner />}
|
loadingContent={<Spinner />}
|
||||||
|
loadingState={loadingState}
|
||||||
>
|
>
|
||||||
{(item) => (
|
{(item) => (
|
||||||
<TableRow key={item.name}>
|
<TableRow key={item?.name}>
|
||||||
{(columnKey) => <TableCell>{getKeyValue(item, columnKey)}</TableCell>}
|
{(columnKey) => <TableCell>{getKeyValue(item, columnKey)}</TableCell>}
|
||||||
</TableRow>
|
</TableRow>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -257,8 +257,7 @@ You can use the [Pagination](/components/pagination) component to paginate the t
|
|||||||
|
|
||||||
### Async Pagination
|
### Async Pagination
|
||||||
|
|
||||||
It is also possible to use the [Pagination](/components/pagination) component to paginate the table asynchronously. To fetch the data, we are using the `useAsyncList` hook from [@react-stately/data](https://react-spectrum.adobe.com/react-stately/useAsyncList.html).
|
It is also possible to use the [Pagination](/components/pagination) component to paginate the table asynchronously. To fetch the data, we are using the `useSWR` hook from [SWR](https://swr.vercel.app/docs/pagination).
|
||||||
Please check the installation instructions in the [Sorting Rows](#sorting-rows) section.
|
|
||||||
|
|
||||||
<CodeDemo
|
<CodeDemo
|
||||||
asIframe
|
asIframe
|
||||||
|
|||||||
@ -18,17 +18,17 @@
|
|||||||
"@codesandbox/sandpack-react": "^2.6.4",
|
"@codesandbox/sandpack-react": "^2.6.4",
|
||||||
"@mapbox/rehype-prism": "^0.6.0",
|
"@mapbox/rehype-prism": "^0.6.0",
|
||||||
"@nextui-org/aria-utils": "workspace:*",
|
"@nextui-org/aria-utils": "workspace:*",
|
||||||
|
"@nextui-org/badge": "workspace:*",
|
||||||
|
"@nextui-org/code": "workspace:*",
|
||||||
|
"@nextui-org/divider": "workspace:*",
|
||||||
|
"@nextui-org/kbd": "workspace:*",
|
||||||
"@nextui-org/react": "workspace:*",
|
"@nextui-org/react": "workspace:*",
|
||||||
"@nextui-org/shared-icons": "workspace:*",
|
"@nextui-org/shared-icons": "workspace:*",
|
||||||
"@nextui-org/shared-utils": "workspace:*",
|
"@nextui-org/shared-utils": "workspace:*",
|
||||||
"@nextui-org/theme": "workspace:*",
|
|
||||||
"@nextui-org/spacer": "workspace:*",
|
|
||||||
"@nextui-org/kbd": "workspace:*",
|
|
||||||
"@nextui-org/code": "workspace:*",
|
|
||||||
"@nextui-org/badge": "workspace:*",
|
|
||||||
"@nextui-org/skeleton": "workspace:*",
|
"@nextui-org/skeleton": "workspace:*",
|
||||||
|
"@nextui-org/spacer": "workspace:*",
|
||||||
"@nextui-org/spinner": "workspace:*",
|
"@nextui-org/spinner": "workspace:*",
|
||||||
"@nextui-org/divider": "workspace:*",
|
"@nextui-org/theme": "workspace:*",
|
||||||
"@nextui-org/use-clipboard": "workspace:*",
|
"@nextui-org/use-clipboard": "workspace:*",
|
||||||
"@nextui-org/use-infinite-scroll": "workspace:*",
|
"@nextui-org/use-infinite-scroll": "workspace:*",
|
||||||
"@nextui-org/use-is-mobile": "workspace:*",
|
"@nextui-org/use-is-mobile": "workspace:*",
|
||||||
@ -84,6 +84,7 @@
|
|||||||
"scroll-into-view-if-needed": "3.0.10",
|
"scroll-into-view-if-needed": "3.0.10",
|
||||||
"sharp": "^0.32.1",
|
"sharp": "^0.32.1",
|
||||||
"shelljs": "^0.8.4",
|
"shelljs": "^0.8.4",
|
||||||
|
"swr": "^2.2.1",
|
||||||
"tailwind-variants": "^0.1.13",
|
"tailwind-variants": "^0.1.13",
|
||||||
"unified": "^9.2.2",
|
"unified": "^9.2.2",
|
||||||
"unist-util-visit": "^4.1.2",
|
"unist-util-visit": "^4.1.2",
|
||||||
|
|||||||
@ -319,7 +319,7 @@ const PrimaryActionTemplate = (args: CardProps) => {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
type ListItem = (typeof list)[number];
|
type ListItem = typeof list[number];
|
||||||
|
|
||||||
const handlePress = (item: ListItem) => {
|
const handlePress = (item: ListItem) => {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
|
|||||||
@ -38,9 +38,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nextui-org/checkbox": "workspace:*",
|
"@nextui-org/checkbox": "workspace:*",
|
||||||
"@nextui-org/shared-utils": "workspace:*",
|
|
||||||
"@nextui-org/react-utils": "workspace:*",
|
"@nextui-org/react-utils": "workspace:*",
|
||||||
"@nextui-org/shared-icons": "workspace:*",
|
"@nextui-org/shared-icons": "workspace:*",
|
||||||
|
"@nextui-org/shared-utils": "workspace:*",
|
||||||
"@nextui-org/spacer": "workspace:*",
|
"@nextui-org/spacer": "workspace:*",
|
||||||
"@nextui-org/system": "workspace:*",
|
"@nextui-org/system": "workspace:*",
|
||||||
"@nextui-org/theme": "workspace:*",
|
"@nextui-org/theme": "workspace:*",
|
||||||
@ -49,22 +49,23 @@
|
|||||||
"@react-aria/table": "^3.11.0",
|
"@react-aria/table": "^3.11.0",
|
||||||
"@react-aria/utils": "^3.19.0",
|
"@react-aria/utils": "^3.19.0",
|
||||||
"@react-aria/visually-hidden": "^3.8.3",
|
"@react-aria/visually-hidden": "^3.8.3",
|
||||||
"@react-stately/virtualizer": "^3.6.0",
|
|
||||||
"@react-stately/table": "^3.11.0",
|
"@react-stately/table": "^3.11.0",
|
||||||
|
"@react-stately/virtualizer": "^3.6.0",
|
||||||
"@react-types/grid": "^3.2.0",
|
"@react-types/grid": "^3.2.0",
|
||||||
"@react-types/table": "^3.8.0"
|
"@react-types/table": "^3.8.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nextui-org/chip": "workspace:*",
|
|
||||||
"@nextui-org/button": "workspace:*",
|
"@nextui-org/button": "workspace:*",
|
||||||
"@nextui-org/spinner": "workspace:*",
|
"@nextui-org/chip": "workspace:*",
|
||||||
"@nextui-org/pagination": "workspace:*",
|
"@nextui-org/pagination": "workspace:*",
|
||||||
"@nextui-org/use-infinite-scroll": "workspace:*",
|
"@nextui-org/spinner": "workspace:*",
|
||||||
"@nextui-org/tooltip": "workspace:*",
|
"@nextui-org/tooltip": "workspace:*",
|
||||||
|
"@nextui-org/use-infinite-scroll": "workspace:*",
|
||||||
"@nextui-org/user": "workspace:*",
|
"@nextui-org/user": "workspace:*",
|
||||||
"@react-stately/data": "^3.10.1",
|
"@react-stately/data": "^3.10.1",
|
||||||
"clean-package": "2.2.0",
|
"clean-package": "2.2.0",
|
||||||
"react": "^18.0.0"
|
"react": "^18.0.0",
|
||||||
|
"swr": "^2.2.1"
|
||||||
},
|
},
|
||||||
"clean-package": "../../../clean-package.config.json"
|
"clean-package": "../../../clean-package.config.json"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import React from "react";
|
import React, {useMemo} from "react";
|
||||||
import {Meta} from "@storybook/react";
|
import {Meta} from "@storybook/react";
|
||||||
import {table} from "@nextui-org/theme";
|
import {table} from "@nextui-org/theme";
|
||||||
import {User} from "@nextui-org/user";
|
import {User} from "@nextui-org/user";
|
||||||
@ -10,6 +10,7 @@ import {Tooltip} from "@nextui-org/tooltip";
|
|||||||
import {EditIcon, DeleteIcon, EyeIcon} from "@nextui-org/shared-icons";
|
import {EditIcon, DeleteIcon, EyeIcon} from "@nextui-org/shared-icons";
|
||||||
import {useInfiniteScroll} from "@nextui-org/use-infinite-scroll";
|
import {useInfiniteScroll} from "@nextui-org/use-infinite-scroll";
|
||||||
import {useAsyncList} from "@react-stately/data";
|
import {useAsyncList} from "@react-stately/data";
|
||||||
|
import useSWR from "swr";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Table,
|
Table,
|
||||||
@ -236,7 +237,7 @@ const CustomCellTemplate = (args: TableProps) => {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
type User = (typeof users)[0];
|
type User = typeof users[0];
|
||||||
|
|
||||||
const statusColorMap: Record<string, ChipProps["color"]> = {
|
const statusColorMap: Record<string, ChipProps["color"]> = {
|
||||||
active: "success",
|
active: "success",
|
||||||
@ -376,7 +377,7 @@ const CustomCellWithClassnamesTemplate = (args: TableProps) => {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
type User = (typeof users)[0];
|
type User = typeof users[0];
|
||||||
|
|
||||||
const statusColorMap: Record<string, ChipProps["color"]> = {
|
const statusColorMap: Record<string, ChipProps["color"]> = {
|
||||||
active: "success",
|
active: "success",
|
||||||
@ -758,38 +759,25 @@ const PaginatedTemplate = (args: TableProps) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const fetcher = (...args: Parameters<typeof fetch>) => fetch(...args).then((res) => res.json());
|
||||||
|
|
||||||
const AsyncPaginatedTemplate = (args: TableProps) => {
|
const AsyncPaginatedTemplate = (args: TableProps) => {
|
||||||
const [page, setPage] = React.useState(1);
|
const [page, setPage] = React.useState(1);
|
||||||
const [total, setTotal] = React.useState(0);
|
|
||||||
|
const {data, isLoading} = useSWR<{
|
||||||
|
count: number;
|
||||||
|
results: SWCharacter[];
|
||||||
|
}>(`https://swapi.py4e.com/api/people?page=${page}`, fetcher, {
|
||||||
|
keepPreviousData: true,
|
||||||
|
});
|
||||||
|
|
||||||
const rowsPerPage = 10;
|
const rowsPerPage = 10;
|
||||||
|
|
||||||
let list = useAsyncList<SWCharacter>({
|
const pages = useMemo(() => {
|
||||||
async load({signal, cursor}) {
|
return data?.count ? Math.ceil(data?.count / rowsPerPage) : 0;
|
||||||
// If no cursor is available, then we're loading the first page.
|
}, [data?.count, rowsPerPage]);
|
||||||
// Otherwise, the cursor is the next URL to load, as returned from the previous page.
|
|
||||||
const res = await fetch(cursor || "https://swapi.py4e.com/api/people/?search=", {signal});
|
|
||||||
let json = await res.json();
|
|
||||||
|
|
||||||
setTotal(json.count);
|
const loadingState = isLoading || data?.results.length === 0 ? "loading" : "idle";
|
||||||
|
|
||||||
return {
|
|
||||||
items: json.results,
|
|
||||||
cursor: json.next,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const pages = Math.ceil(total / rowsPerPage);
|
|
||||||
|
|
||||||
const items = React.useMemo(() => {
|
|
||||||
const start = (page - 1) * rowsPerPage;
|
|
||||||
const end = start + rowsPerPage;
|
|
||||||
|
|
||||||
return list.items.slice(start, end);
|
|
||||||
}, [page, list.items?.length, list.loadingState]);
|
|
||||||
|
|
||||||
const loadingState = items.length === 0 ? "loading" : list.loadingState;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Table
|
<Table
|
||||||
@ -804,12 +792,7 @@ const AsyncPaginatedTemplate = (args: TableProps) => {
|
|||||||
color="primary"
|
color="primary"
|
||||||
page={page}
|
page={page}
|
||||||
total={pages}
|
total={pages}
|
||||||
onChange={(page) => {
|
onChange={(page) => setPage(page)}
|
||||||
if (page >= list.items.length / rowsPerPage) {
|
|
||||||
list.loadMore();
|
|
||||||
}
|
|
||||||
setPage(page);
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : null
|
) : null
|
||||||
@ -822,9 +805,13 @@ const AsyncPaginatedTemplate = (args: TableProps) => {
|
|||||||
<TableColumn key="mass">Mass</TableColumn>
|
<TableColumn key="mass">Mass</TableColumn>
|
||||||
<TableColumn key="birth_year">Birth year</TableColumn>
|
<TableColumn key="birth_year">Birth year</TableColumn>
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
<TableBody items={items} loadingContent={<Spinner />} loadingState={loadingState}>
|
<TableBody
|
||||||
|
items={data?.results ?? []}
|
||||||
|
loadingContent={<Spinner />}
|
||||||
|
loadingState={loadingState}
|
||||||
|
>
|
||||||
{(item) => (
|
{(item) => (
|
||||||
<TableRow key={item.name}>
|
<TableRow key={item?.name}>
|
||||||
{(columnKey) => <TableCell>{getKeyValue(item, columnKey)}</TableCell>}
|
{(columnKey) => <TableCell>{getKeyValue(item, columnKey)}</TableCell>}
|
||||||
</TableRow>
|
</TableRow>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -65,7 +65,7 @@ export const spacingScaleKeys = [
|
|||||||
|
|
||||||
export const mappedSpacingScaleKeys = spacingScaleKeys.map((key) => `unit-${key}`);
|
export const mappedSpacingScaleKeys = spacingScaleKeys.map((key) => `unit-${key}`);
|
||||||
|
|
||||||
export type SpacingScaleKeys = (typeof spacingScaleKeys)[number];
|
export type SpacingScaleKeys = typeof spacingScaleKeys[number];
|
||||||
|
|
||||||
export type SpacingScale = Partial<Record<SpacingScaleKeys, string>>;
|
export type SpacingScale = Partial<Record<SpacingScaleKeys, string>>;
|
||||||
|
|
||||||
|
|||||||
16
pnpm-lock.yaml
generated
16
pnpm-lock.yaml
generated
@ -471,6 +471,9 @@ importers:
|
|||||||
shelljs:
|
shelljs:
|
||||||
specifier: ^0.8.4
|
specifier: ^0.8.4
|
||||||
version: 0.8.5
|
version: 0.8.5
|
||||||
|
swr:
|
||||||
|
specifier: ^2.2.1
|
||||||
|
version: 2.2.1(react@18.2.0)
|
||||||
tailwind-variants:
|
tailwind-variants:
|
||||||
specifier: ^0.1.13
|
specifier: ^0.1.13
|
||||||
version: 0.1.13(tailwindcss@3.3.3)
|
version: 0.1.13(tailwindcss@3.3.3)
|
||||||
@ -2009,6 +2012,9 @@ importers:
|
|||||||
react:
|
react:
|
||||||
specifier: ^18.2.0
|
specifier: ^18.2.0
|
||||||
version: 18.2.0
|
version: 18.2.0
|
||||||
|
swr:
|
||||||
|
specifier: ^2.2.1
|
||||||
|
version: 2.2.1(react@18.2.0)
|
||||||
|
|
||||||
packages/components/tabs:
|
packages/components/tabs:
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -22956,6 +22962,15 @@ packages:
|
|||||||
stable: 0.1.8
|
stable: 0.1.8
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/swr@2.2.1(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-KJVA7dGtOBeZ+2sycEuzUfVIP5lZ/cd0xjevv85n2YG0x1uHJQicjAtahVZL6xG3+TjqhbBqimwYzVo3saeVXQ==}
|
||||||
|
peerDependencies:
|
||||||
|
react: ^18.2.0
|
||||||
|
dependencies:
|
||||||
|
client-only: 0.0.1
|
||||||
|
react: 18.2.0
|
||||||
|
use-sync-external-store: 1.2.0(react@18.2.0)
|
||||||
|
|
||||||
/symbol-tree@3.2.4:
|
/symbol-tree@3.2.4:
|
||||||
resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==}
|
resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==}
|
||||||
dev: true
|
dev: true
|
||||||
@ -24036,7 +24051,6 @@ packages:
|
|||||||
react: ^18.2.0
|
react: ^18.2.0
|
||||||
dependencies:
|
dependencies:
|
||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
dev: false
|
|
||||||
|
|
||||||
/use@3.1.1:
|
/use@3.1.1:
|
||||||
resolution: {integrity: sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==}
|
resolution: {integrity: sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user