From 4871c22ff1c3dc0872c946db089272e04b002aab Mon Sep 17 00:00:00 2001 From: Jebbaited Date: Wed, 15 May 2024 17:38:06 +0300 Subject: [PATCH 1/2] feature: add the ability to go to the specific page in pagination --- components/ui/pagination.tsx | 62 ++++++++++++++++++++++++++++++------ 1 file changed, 53 insertions(+), 9 deletions(-) diff --git a/components/ui/pagination.tsx b/components/ui/pagination.tsx index d5239fd5..1f3c785e 100644 --- a/components/ui/pagination.tsx +++ b/components/ui/pagination.tsx @@ -1,12 +1,14 @@ 'use client'; import clsx from 'clsx'; +import { ChangeEvent, useEffect, useState } from 'react'; import AntDesignArrowLeftOutlined from '~icons/ant-design/arrow-left-outlined'; import AntDesignArrowRightOutlined from '~icons/ant-design/arrow-right-outlined'; import { range } from '@antfu/utils'; import { Button } from '@/components/ui/button'; +import { Input } from '@/components/ui/input'; import { cn } from '@/utils/utils'; interface Props { @@ -16,6 +18,8 @@ interface Props { } const Component = ({ page, pages, setPage }: Props) => { + const [pageToMove, setPageToMove] = useState(''); + const generatePaginationArr = () => { const pagArr: (number | undefined)[] = [1]; @@ -44,9 +48,25 @@ const Component = ({ page, pages, setPage }: Props) => { } pagArr.push(...range(2, pages + 1)); + return pagArr; }; + const handleMoveToPage = (event: ChangeEvent) => { + const value = event.target.value; + const digitsOnlyRegex = /^(?!0)\d+$/; + + if (!digitsOnlyRegex.test(value)) return setPageToMove(''); + + if (parseInt(value) > pages) return; + + setPageToMove(value); + }; + + useEffect(() => { + setPageToMove(''); + }, [page]); + return (
{generatePaginationArr().map((v, index) => { + if (v) { + return ( + + ); + } + return ( - + value={pageToMove} + placeholder="..." + onChange={handleMoveToPage} + onKeyDown={(e) => { + if (!pageToMove) return; + + if (e.key === 'Enter') { + e.preventDefault(); + setPage(parseInt(pageToMove)); + setPageToMove(''); + } + }} + className={cn( + 'size-9 sm:size-10', + pageToMove && 'focus-visible:none w-16 sm:w-16', + )} + /> ); })} + ); +}; + +interface PaginationButtonProps { + value: number; + page: number; + setPage: (page: number) => void; +} + +const PaginationButton: FC = ({ + value, + page, + setPage, +}) => { + return ( + + ); +}; + +interface PaginationInputProps { + pages: number; + page: number; + setPage: (page: number) => void; +} + +const PaginationInput: FC = ({ + page, + setPage, + pages, +}) => { const [pageToMove, setPageToMove] = useState(''); + const handleMoveToPage = (event: ChangeEvent) => { + const value = event.target.value; + const digitsOnlyRegex = /^(?!0)\d+$/; + + if (!digitsOnlyRegex.test(value)) return setPageToMove(''); + + if (parseInt(value) > pages) return; + + setPageToMove(value); + }; + + useEffect(() => { + setPageToMove(''); + }, [page]); + + return ( + { + if (!pageToMove) return; + + if (e.key === 'Enter') { + e.preventDefault(); + setPage(parseInt(pageToMove)); + setPageToMove(''); + } + }} + className={cn('size-9 sm:size-10', pageToMove && ' w-16 sm:w-16')} + /> + ); +}; + +const Pagination = ({ page, pages, setPage }: Props) => { const generatePaginationArr = () => { - const pagArr: (number | undefined)[] = [1]; + const pagArr: PaginationType[] = [1]; if (pages >= 7) { if (pages - page <= 3) { - pagArr.push(undefined); + pagArr.push('input'); pagArr.push(...range(pages - 4, pages + 1)); return pagArr; @@ -33,15 +116,15 @@ const Component = ({ page, pages, setPage }: Props) => { if (page < 5) { pagArr.push(...range(2, 6)); - pagArr.push(undefined); + pagArr.push('input'); pagArr.push(pages); return pagArr; } - pagArr.push(undefined); + pagArr.push('empty'); pagArr.push(...range(page - 1, page + 2)); - pagArr.push(undefined); + pagArr.push('input'); pagArr.push(pages); return pagArr; @@ -52,21 +135,6 @@ const Component = ({ page, pages, setPage }: Props) => { return pagArr; }; - const handleMoveToPage = (event: ChangeEvent) => { - const value = event.target.value; - const digitsOnlyRegex = /^(?!0)\d+$/; - - if (!digitsOnlyRegex.test(value)) return setPageToMove(''); - - if (parseInt(value) > pages) return; - - setPageToMove(value); - }; - - useEffect(() => { - setPageToMove(''); - }, [page]); - return (
- {generatePaginationArr().map((v, index) => { - if (v) { + {generatePaginationArr().map((value, index) => { + if (typeof value === 'number') { return ( - + value={value} + page={page} + setPage={setPage} + /> ); } + if (value === 'empty') { + return ; + } + return ( - { - if (!pageToMove) return; - - if (e.key === 'Enter') { - e.preventDefault(); - setPage(parseInt(pageToMove)); - setPageToMove(''); - } - }} - className={cn( - 'size-9 sm:size-10', - pageToMove && 'focus-visible:none w-16 sm:w-16', - )} /> ); })} @@ -121,7 +176,7 @@ const Component = ({ page, pages, setPage }: Props) => { variant="outline" onClick={() => setPage(page + 1)} disabled={page === pages} - className={clsx('text-xs h-9 w-9 sm:h-10 sm:w-10')} + className={cn('size-9 text-xs sm:size-10')} > @@ -129,4 +184,4 @@ const Component = ({ page, pages, setPage }: Props) => { ); }; -export default Component; +export default Pagination;