Write your answer here
Loading editor...
Dev4Room
Loading editor...
Search for a command to run...
How to implement Tanstack Form with new shadcn Field component?
How to integrate Tanstack Query with oRPC?
What is the difference between ExpressJS and NextJS for backend development?
Why does pandas.concat in Python 3.13 result in MemoryError with small DataFrames when using axis=1?
Random question to test global search


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:
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