Write your answer here
Loading editor...
Dev4Room
Loading editor...
Search for a command to run...


The answer board is empty. Make it filled with your brilliant answer.
In order to make the component optimized for Next.js, I used component instead of for the PaginationLink component.
And here's the full implementation of next-navigation component:
Why does pandas.concat in Python 3.13 result in MemoryError with small DataFrames when using axis=1?
1type PaginationLinkProps = {
2 isActive?: boolean;
3} & Pick<React.ComponentProps<typeof Button>, "size"> &
4 React.ComponentProps<typeof Link>;
5
6function PaginationLink({
7 className,
8 isActive,
9 size = "icon",
10 ...props
11}: PaginationLinkProps) {
12 return (
13 <Link
14 aria-current={isActive ? "page" : undefined}
15 data-slot="pagination-link"
16 data-active={isActive}
17 className={cn(
18 buttonVariants({
19 variant: isActive ? "default" : "ghost",
20 size,
21 }),
22 className,
23 )}
24 {...props}
25 />
26 );
27}
1type PaginationLinkProps = {
2 isActive?: boolean;
3} & Pick<React.ComponentProps<typeof Button>, "size"> &
4 React.ComponentProps<typeof Link>;
5
6function PaginationLink({
7 className,
8 isActive,
9 size = "icon",
10 ...props
11}: PaginationLinkProps) {
12 return (
13 <Link
14 aria-current={isActive ? "page" : undefined}
15 data-slot="pagination-link"
16 data-active={isActive}
17 className={cn(
18 buttonVariants({
19 variant: isActive ? "default" : "ghost",
20 size,
21 }),
22 className,
23 )}
24 {...props}
25 />
26 );
27}
1"use client";
2
3import { type ReactNode, useCallback } from "react";
4import {
5 Pagination,
6 PaginationContent,
7 PaginationEllipsis,
8 PaginationItem,
9 PaginationLink,
10 PaginationNext,
11 PaginationPrevious,
12} from "./pagination";
13import { usePathname, useSearchParams } from "next/navigation";
14import { cn } from "@/lib/utils";
15import { Route } from "next";
16
17export interface NextPaginationProps {
18 totalCount: number;
19 pageSize?: number | string | undefined;
20 page?: number | string | undefined;
21 pageSearchParam?: string;
22 className?: string;
23 scroll?: boolean;
24}
25
26export function NextPagination({
27 pageSize = 10,
28 totalCount,
29 page = 1,
30 pageSearchParam,
31 className,
32 scroll = true,
33}: NextPaginationProps) {
34 const pathname = usePathname();
35 const searchParams = useSearchParams();
36
37 const totalPageCount = Math.max(1, Math.ceil(totalCount / Number(pageSize)));
38
39 const buildLink = useCallback(
40 (newPage: number) => {
41 const key = pageSearchParam || "page";
42 if (!searchParams) return `${pathname}?${key}=${newPage}`;
43 const newSearchParams = new URLSearchParams(searchParams);
44 newSearchParams.set(key, String(newPage));
45 return `${pathname}?${newSearchParams.toString()}`;
46 },
47 [searchParams, pathname, pageSearchParam],
48 );
49
50 const renderPageNumbers = () => {
51 const items: ReactNode[] = [];
52 const maxVisiblePages = 5;
53
54 if (totalPageCount <= maxVisiblePages) {
55 for (let i = 1; i <= totalPageCount; i++) {
56 items.push(
57 <PaginationItem key={i}>
58 <PaginationLink
59 href={buildLink(i) as Route}
60 isActive={Number(page) === i}
61 scroll={scroll}
62 >
63 {i}
64 </PaginationLink>
65 </PaginationItem>,
66 );
67 }
68 } else {
69 items.push(
70 <PaginationItem key={1}>
71 <PaginationLink
72 href={buildLink(1) as Route}
73 isActive={Number(page) === 1}
74 scroll={scroll}
75 >
76 1
77 </PaginationLink>
78 </PaginationItem>,
79 );
80
81 if (Number(page) > 3) {
82 items.push(
83 <PaginationItem key="ellipsis-start">
84 <PaginationEllipsis />
85 </PaginationItem>,
86 );
87 }
88
89 const start = Math.max(2, Number(page) - 1);
90 const end = Math.min(totalPageCount - 1, Number(page) + 1);
91
92 for (let i = start; i <= end; i++) {
93 items.push(
94 <PaginationItem key={i}>
95 <PaginationLink
96 href={buildLink(i) as Route}
97 isActive={Number(page) === i}
98 scroll={scroll}
99 >
100 {i}
101 </PaginationLink>
102 </PaginationItem>,
103 );
104 }
105
106 if (Number(page) < totalPageCount - 2) {
107 items.push(
108 <PaginationItem key="ellipsis-end">
109 <PaginationEllipsis />
110 </PaginationItem>,
111 );
112 }
113
114 items.push(
115 <PaginationItem key={totalPageCount}>
116 <PaginationLink
117 href={buildLink(totalPageCount) as Route}
118 isActive={Number(page) === totalPageCount}
119 scroll={scroll}
120 >
121 {String(totalPageCount)}
122 </PaginationLink>
123 </PaginationItem>,
124 );
125 }
126
127 return items;
128 };
129
130 return (
131 <div
132 className={cn(
133 "gap-2 w-full",
134 totalCount > Number(pageSize) ? "flex-center" : "hidden",
135 className,
136 )}
137 >
138 <Pagination>
139 <PaginationContent className="max-sm:gap-0">
140 <PaginationItem>
141 <PaginationPrevious
142 href={buildLink(Math.max(Number(page) - 1, 1)) as Route}
143 aria-disabled={Number(page) === 1}
144 tabIndex={Number(page) === 1 ? -1 : undefined}
145 scroll={scroll}
146 className={
147 Number(page) === 1
148 ? "pointer-events-none opacity-50"
149 : undefined
150 }
151 />
152 </PaginationItem>
153 {renderPageNumbers()}
154 <PaginationItem>
155 <PaginationNext
156 href={
157 buildLink(Math.min(Number(page) + 1, totalPageCount)) as Route
158 }
159 aria-disabled={Number(page) === totalPageCount}
160 tabIndex={Number(page) === totalPageCount ? -1 : undefined}
161 scroll={scroll}
162 className={
163 Number(page) === totalPageCount
164 ? "pointer-events-none opacity-50"
165 : undefined
166 }
167 />
168 </PaginationItem>
169 </PaginationContent>
170 </Pagination>
171 </div>
172 );
173}
174
1"use client";
2
3import { type ReactNode, useCallback } from "react";
4import {
5 Pagination,
6 PaginationContent,
7 PaginationEllipsis,
8 PaginationItem,
9 PaginationLink,
10 PaginationNext,
11 PaginationPrevious,
12} from "./pagination";
13import { usePathname, useSearchParams } from "next/navigation";
14import { cn } from "@/lib/utils";
15import { Route } from "next";
16
17export interface NextPaginationProps {
18 totalCount: number;
19 pageSize?: number | string | undefined;
20 page?: number | string | undefined;
21 pageSearchParam?: string;
22 className?: string;
23 scroll?: boolean;
24}
25
26export function NextPagination({
27 pageSize = 10,
28 totalCount,
29 page = 1,
30 pageSearchParam,
31 className,
32 scroll = true,
33}: NextPaginationProps) {
34 const pathname = usePathname();
35 const searchParams = useSearchParams();
36
37 const totalPageCount = Math.max(1, Math.ceil(totalCount / Number(pageSize)));
38
39 const buildLink = useCallback(
40 (newPage: number) => {
41 const key = pageSearchParam || "page";
42 if (!searchParams) return `${pathname}?${key}=${newPage}`;
43 const newSearchParams = new URLSearchParams(searchParams);
44 newSearchParams.set(key, String(newPage));
45 return `${pathname}?${newSearchParams.toString()}`;
46 },
47 [searchParams, pathname, pageSearchParam],
48 );
49
50 const renderPageNumbers = () => {
51 const items: ReactNode[] = [];
52 const maxVisiblePages = 5;
53
54 if (totalPageCount <= maxVisiblePages) {
55 for (let i = 1; i <= totalPageCount; i++) {
56 items.push(
57 <PaginationItem key={i}>
58 <PaginationLink
59 href={buildLink(i) as Route}
60 isActive={Number(page) === i}
61 scroll={scroll}
62 >
63 {i}
64 </PaginationLink>
65 </PaginationItem>,
66 );
67 }
68 } else {
69 items.push(
70 <PaginationItem key={1}>
71 <PaginationLink
72 href={buildLink(1) as Route}
73 isActive={Number(page) === 1}
74 scroll={scroll}
75 >
76 1
77 </PaginationLink>
78 </PaginationItem>,
79 );
80
81 if (Number(page) > 3) {
82 items.push(
83 <PaginationItem key="ellipsis-start">
84 <PaginationEllipsis />
85 </PaginationItem>,
86 );
87 }
88
89 const start = Math.max(2, Number(page) - 1);
90 const end = Math.min(totalPageCount - 1, Number(page) + 1);
91
92 for (let i = start; i <= end; i++) {
93 items.push(
94 <PaginationItem key={i}>
95 <PaginationLink
96 href={buildLink(i) as Route}
97 isActive={Number(page) === i}
98 scroll={scroll}
99 >
100 {i}
101 </PaginationLink>
102 </PaginationItem>,
103 );
104 }
105
106 if (Number(page) < totalPageCount - 2) {
107 items.push(
108 <PaginationItem key="ellipsis-end">
109 <PaginationEllipsis />
110 </PaginationItem>,
111 );
112 }
113
114 items.push(
115 <PaginationItem key={totalPageCount}>
116 <PaginationLink
117 href={buildLink(totalPageCount) as Route}
118 isActive={Number(page) === totalPageCount}
119 scroll={scroll}
120 >
121 {String(totalPageCount)}
122 </PaginationLink>
123 </PaginationItem>,
124 );
125 }
126
127 return items;
128 };
129
130 return (
131 <div
132 className={cn(
133 "gap-2 w-full",
134 totalCount > Number(pageSize) ? "flex-center" : "hidden",
135 className,
136 )}
137 >
138 <Pagination>
139 <PaginationContent className="max-sm:gap-0">
140 <PaginationItem>
141 <PaginationPrevious
142 href={buildLink(Math.max(Number(page) - 1, 1)) as Route}
143 aria-disabled={Number(page) === 1}
144 tabIndex={Number(page) === 1 ? -1 : undefined}
145 scroll={scroll}
146 className={
147 Number(page) === 1
148 ? "pointer-events-none opacity-50"
149 : undefined
150 }
151 />
152 </PaginationItem>
153 {renderPageNumbers()}
154 <PaginationItem>
155 <PaginationNext
156 href={
157 buildLink(Math.min(Number(page) + 1, totalPageCount)) as Route
158 }
159 aria-disabled={Number(page) === totalPageCount}
160 tabIndex={Number(page) === totalPageCount ? -1 : undefined}
161 scroll={scroll}
162 className={
163 Number(page) === totalPageCount
164 ? "pointer-events-none opacity-50"
165 : undefined
166 }
167 />
168 </PaginationItem>
169 </PaginationContent>
170 </Pagination>
171 </div>
172 );
173}
174