mirror of
https://github.com/nonebot/nonebot2.git
synced 2025-09-08 13:06:46 +00:00
🚧 add tag selection
This commit is contained in:
@ -1,5 +1,5 @@
|
||||
import clsx from "clsx";
|
||||
import React, { useCallback, useRef } from "react";
|
||||
import ReactPaginate from "react-paginate";
|
||||
import { usePagination } from "react-use-pagination";
|
||||
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
@ -9,11 +9,19 @@ import styles from "./styles.module.css";
|
||||
|
||||
export default function Paginate({
|
||||
totalPages,
|
||||
setPreviousPage,
|
||||
setNextPage,
|
||||
setPage,
|
||||
currentPage,
|
||||
previousEnabled,
|
||||
nextEnabled,
|
||||
}: ReturnType<typeof usePagination>): JSX.Element {
|
||||
const ref = useRef<HTMLElement>();
|
||||
const maxWidth = useContentWidth(ref.current?.parentElement ?? undefined);
|
||||
const maxLength = Math.min(
|
||||
(maxWidth && Math.floor(maxWidth / 50) - 2) || totalPages,
|
||||
totalPages
|
||||
);
|
||||
|
||||
const onPageChange = useCallback(
|
||||
(selectedItem: { selected: number }) => {
|
||||
@ -21,27 +29,74 @@ export default function Paginate({
|
||||
},
|
||||
[setPage]
|
||||
);
|
||||
const range = useCallback((start: number, end: number) => {
|
||||
const result = [];
|
||||
start = start > 0 ? start : 1;
|
||||
for (let i = start; i <= end; i++) {
|
||||
result.push(i);
|
||||
}
|
||||
return result;
|
||||
}, []);
|
||||
|
||||
// FIXME: responsive width
|
||||
const pages: (React.ReactNode | number)[] = [];
|
||||
const ellipsis = <FontAwesomeIcon icon="ellipsis-h" />;
|
||||
|
||||
const even = maxLength % 2 === 0 ? 1 : 0;
|
||||
const left = Math.floor(maxLength / 2);
|
||||
const right = totalPages - left + even + 1;
|
||||
currentPage = currentPage + 1;
|
||||
|
||||
if (totalPages <= maxLength) {
|
||||
pages.push(...range(1, totalPages));
|
||||
} else if (currentPage > left && currentPage < right) {
|
||||
const firstItem = 1;
|
||||
const lastItem = totalPages;
|
||||
const start = currentPage - left + 2;
|
||||
const end = currentPage + left - 2 - even;
|
||||
const secondItem = start - 1 === firstItem + 1 ? 2 : ellipsis;
|
||||
const beforeLastItem = end + 1 === lastItem - 1 ? end + 1 : ellipsis;
|
||||
|
||||
pages.push(1, secondItem, ...range(start, end), beforeLastItem, totalPages);
|
||||
} else if (currentPage === left) {
|
||||
const end = currentPage + left - 1 - even;
|
||||
pages.push(...range(1, end), ellipsis, totalPages);
|
||||
} else if (currentPage === right) {
|
||||
const start = currentPage - left + 1;
|
||||
pages.push(1, ellipsis, ...range(start, totalPages));
|
||||
} else {
|
||||
pages.push(...range(1, left), ellipsis, ...range(right, totalPages));
|
||||
}
|
||||
|
||||
return (
|
||||
<nav role="navigation" aria-label="Pagination Navigation" ref={ref}>
|
||||
<ReactPaginate
|
||||
pageCount={totalPages}
|
||||
forcePage={currentPage}
|
||||
onPageChange={onPageChange}
|
||||
containerClassName={styles.container}
|
||||
pageClassName={styles.li}
|
||||
pageLinkClassName={styles.a}
|
||||
previousClassName={styles.li}
|
||||
previousLinkClassName={styles.a}
|
||||
nextClassName={styles.li}
|
||||
nextLinkClassName={styles.a}
|
||||
activeLinkClassName={styles.active}
|
||||
disabledLinkClassName={styles.disabled}
|
||||
breakLabel={<FontAwesomeIcon icon="ellipsis-h" />}
|
||||
previousLabel={<FontAwesomeIcon icon="chevron-left" />}
|
||||
nextLabel={<FontAwesomeIcon icon="chevron-right" />}
|
||||
></ReactPaginate>
|
||||
<ul className={styles.container}>
|
||||
<li
|
||||
className={clsx(styles.li, { [styles.disabled]: !previousEnabled })}
|
||||
>
|
||||
<button className={styles.button} onClick={setPreviousPage}>
|
||||
<FontAwesomeIcon icon="chevron-left" />
|
||||
</button>
|
||||
</li>
|
||||
{pages.map((page, index) => (
|
||||
<li className={styles.li} key={index}>
|
||||
<button
|
||||
className={clsx(styles.button, {
|
||||
[styles.active]: page === currentPage,
|
||||
"pointer-events-none": typeof page !== "number",
|
||||
})}
|
||||
onClick={() => typeof page === "number" && setPage(page - 1)}
|
||||
>
|
||||
{page}
|
||||
</button>
|
||||
</li>
|
||||
))}
|
||||
<li className={clsx(styles.li, { [styles.disabled]: !nextEnabled })}>
|
||||
<button className={styles.button} onClick={setNextPage}>
|
||||
<FontAwesomeIcon icon="chevron-right" />
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
@apply flex items-center;
|
||||
}
|
||||
|
||||
.a {
|
||||
.button {
|
||||
height: 34px;
|
||||
width: auto;
|
||||
min-width: 34px;
|
||||
@ -15,12 +15,12 @@
|
||||
@apply text-black bg-light-nonepress-100;
|
||||
}
|
||||
|
||||
:global(.dark) .a {
|
||||
:global(.dark) .button {
|
||||
@apply border-dark-nonepress-200 shadow-dark-nonepress-300;
|
||||
@apply text-white bg-dark-nonepress-100;
|
||||
}
|
||||
|
||||
.a.active {
|
||||
.button.active {
|
||||
@apply bg-hero text-white border-hero;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user