Files
btrc-hub/frontend/src/components/common/Pagination.tsx
T
みてるぞ 797e67ac37 アニメーション(#139) (#252)
#139

#139

#139

#139

#139

Merge branch 'feature/140' into feature/139

Merge remote-tracking branch 'origin/main' into feature/139

#140

Merge remote-tracking branch 'origin/main' into feature/140

Merge remote-tracking branch 'origin/main' into feature/140

#140 ぼちぼち

Merge remote-tracking branch 'origin/main' into feature/140

#140

#140

#140

#139 アニメーション

Co-authored-by: miteruzo <miteruzo@naver.com>
Reviewed-on: #252
2026-02-05 23:25:27 +09:00

82 lines
2.1 KiB
TypeScript

import { useLocation } from 'react-router-dom'
import PrefetchLink from '@/components/PrefetchLink'
import type { FC } from 'react'
type Props = { page: number
totalPages: number
siblingCount?: number }
const range = (start: number, end: number): number[] =>
[...Array (end - start + 1).keys ()].map (i => start + i)
const getPages = (
page: number,
total: number,
siblingCount: number,
): (number | '…')[] => {
if (total <= 1)
return [1]
const first = 1
const last = total
const left = Math.max (page - siblingCount, first)
const right = Math.min (page + siblingCount, last)
const pages: (number | '…')[] = []
pages.push (first)
if (left > first + 1)
pages.push ('…')
const midStart = Math.max (left, first + 1)
const midEnd = Math.min (right, last - 1)
pages.push (...range (midStart, midEnd))
if (right < last - 1)
pages.push ('…')
if (last !== first)
pages.push (last)
return pages.filter ((v, i, arr) => i === 0 || v !== arr[i - 1])
}
export default (({ page, totalPages, siblingCount = 4 }) => {
const location = useLocation ()
const buildTo = (p: number) => {
const qs = new URLSearchParams (location.search)
qs.set ('page', String (p))
return `${ location.pathname }?${ qs.toString () }`
}
const pages = getPages (page, totalPages, siblingCount)
return (
<nav className="mt-4 flex justify-center" aria-label="Pagination">
<div className="flex items-center gap-2">
{(page > 1)
? <PrefetchLink to={buildTo (page - 1)} aria-label="前のページ">&lt;</PrefetchLink>
: <span aria-hidden>&lt;</span>}
{pages.map ((p, idx) => (
(p === '…')
? <span key={`dots-${ idx }`}></span>
: ((p === page)
? <span key={p} className="font-bold" aria-current="page">{p}</span>
: <PrefetchLink key={p} to={buildTo (p)}>{p}</PrefetchLink>)))}
{(page < totalPages)
? <PrefetchLink to={buildTo (page + 1)} aria-label="次のページ">&gt;</PrefetchLink>
: <span aria-hidden>&gt;</span>}
</div>
</nav>)
}) satisfies FC<Props>