@djangocfg/ui-nextjs 2.1.319 → 2.1.321
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -262
- package/package.json +7 -17
- package/src/index.ts +11 -14
- package/src/animations/AnimatedBackground.tsx +0 -646
- package/src/animations/MouseFollower.tsx +0 -355
- package/src/animations/index.ts +0 -5
- package/src/blocks/ArticleCard.tsx +0 -94
- package/src/blocks/ArticleList.tsx +0 -96
- package/src/blocks/CTASection.tsx +0 -136
- package/src/blocks/FeatureSection.tsx +0 -176
- package/src/blocks/Hero.tsx +0 -102
- package/src/blocks/NewsletterSection.tsx +0 -119
- package/src/blocks/SplitHero/SplitHero.tsx +0 -95
- package/src/blocks/SplitHero/SplitHeroContent.tsx +0 -117
- package/src/blocks/SplitHero/SplitHeroMedia.tsx +0 -67
- package/src/blocks/SplitHero/index.ts +0 -13
- package/src/blocks/SplitHero/types.ts +0 -75
- package/src/blocks/StatsSection.tsx +0 -103
- package/src/blocks/SuperHero.tsx +0 -352
- package/src/blocks/TestimonialSection.tsx +0 -122
- package/src/blocks/index.ts +0 -10
- package/src/components/README.md +0 -2018
- package/src/components/breadcrumb-navigation.tsx +0 -130
- package/src/components/breadcrumb.tsx +0 -133
- package/src/components/dropdown-menu.tsx +0 -220
- package/src/components/index.ts +0 -52
- package/src/components/pagination-static.tsx +0 -344
- package/src/components/pagination.tsx +0 -138
- package/src/components/sidebar.tsx +0 -923
- package/src/components/ssr-pagination.tsx +0 -214
|
@@ -1,344 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* DRF Static Pagination Component
|
|
3
|
-
*
|
|
4
|
-
* Universal pagination component that works with Django REST Framework pagination format.
|
|
5
|
-
* Manages page state internally and provides callbacks for page changes.
|
|
6
|
-
*
|
|
7
|
-
* DRF Pagination Response Format:
|
|
8
|
-
* {
|
|
9
|
-
* "count": 150, // Total number of items
|
|
10
|
-
* "page": 1, // Current page number
|
|
11
|
-
* "pages": 15, // Total number of pages
|
|
12
|
-
* "page_size": 10, // Items per page
|
|
13
|
-
* "has_next": true, // Whether there's a next page
|
|
14
|
-
* "has_previous": false, // Whether there's a previous page
|
|
15
|
-
* "next_page": 2, // Next page number (or null)
|
|
16
|
-
* "previous_page": null, // Previous page number (or null)
|
|
17
|
-
* "results": [...] // Array of items
|
|
18
|
-
* }
|
|
19
|
-
*
|
|
20
|
-
* Usage with SWR:
|
|
21
|
-
* ```tsx
|
|
22
|
-
* import { StaticPagination, useDRFPagination } from '@djangocfg/ui-nextjs';
|
|
23
|
-
*
|
|
24
|
-
* function MyComponent() {
|
|
25
|
-
* const pagination = useDRFPagination();
|
|
26
|
-
* const { data, isLoading } = useMyAPI(pagination.params);
|
|
27
|
-
*
|
|
28
|
-
* return (
|
|
29
|
-
* <div>
|
|
30
|
-
* {data?.results?.map(item => <Item key={item.id} {...item} />)}
|
|
31
|
-
* <StaticPagination data={data} onPageChange={pagination.setPage} />
|
|
32
|
-
* </div>
|
|
33
|
-
* );
|
|
34
|
-
* }
|
|
35
|
-
* ```
|
|
36
|
-
*/
|
|
37
|
-
|
|
38
|
-
"use client"
|
|
39
|
-
|
|
40
|
-
import { ChevronLeft, ChevronRight } from 'lucide-react';
|
|
41
|
-
import React from 'react';
|
|
42
|
-
|
|
43
|
-
import { Button } from '@djangocfg/ui-core/components';
|
|
44
|
-
import { useIsMobile } from '@djangocfg/ui-core/hooks';
|
|
45
|
-
import { cn } from '@djangocfg/ui-core/lib';
|
|
46
|
-
|
|
47
|
-
import {
|
|
48
|
-
Pagination, PaginationContent, PaginationEllipsis, PaginationItem
|
|
49
|
-
} from './pagination';
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* DRF Pagination Response type
|
|
53
|
-
*/
|
|
54
|
-
export interface DRFPaginatedResponse<T = any> {
|
|
55
|
-
count: number;
|
|
56
|
-
page: number;
|
|
57
|
-
pages: number;
|
|
58
|
-
page_size: number;
|
|
59
|
-
has_next: boolean;
|
|
60
|
-
has_previous: boolean;
|
|
61
|
-
next_page?: number | null;
|
|
62
|
-
previous_page?: number | null;
|
|
63
|
-
results: T[];
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
interface StaticPaginationProps {
|
|
67
|
-
/** The DRF paginated response data */
|
|
68
|
-
data?: DRFPaginatedResponse | null;
|
|
69
|
-
/** Callback when page changes */
|
|
70
|
-
onPageChange: (page: number) => void;
|
|
71
|
-
/** Additional CSS class */
|
|
72
|
-
className?: string;
|
|
73
|
-
/** Show pagination info (default: true) */
|
|
74
|
-
showInfo?: boolean;
|
|
75
|
-
/** Maximum visible page numbers (default: 7) */
|
|
76
|
-
maxVisiblePages?: number;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export const StaticPagination: React.FC<StaticPaginationProps> = ({
|
|
80
|
-
data,
|
|
81
|
-
onPageChange,
|
|
82
|
-
className,
|
|
83
|
-
showInfo = true,
|
|
84
|
-
maxVisiblePages = 7,
|
|
85
|
-
}) => {
|
|
86
|
-
const isMobile = useIsMobile();
|
|
87
|
-
|
|
88
|
-
// Don't render if no data or not paginated
|
|
89
|
-
if (!data || !('count' in data) || !('page' in data) || !('pages' in data)) {
|
|
90
|
-
return null;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Extract pagination metadata
|
|
94
|
-
const {
|
|
95
|
-
count: totalItems,
|
|
96
|
-
page: currentPage,
|
|
97
|
-
pages: totalPages,
|
|
98
|
-
page_size: itemsPerPage,
|
|
99
|
-
has_next: hasNextPage,
|
|
100
|
-
has_previous: hasPreviousPage,
|
|
101
|
-
} = data;
|
|
102
|
-
|
|
103
|
-
// Don't render if only one page
|
|
104
|
-
if (totalPages <= 1) {
|
|
105
|
-
return null;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// Generate array of page numbers to display
|
|
109
|
-
const getVisiblePages = (): (number | 'ellipsis')[] => {
|
|
110
|
-
// On mobile, show fewer pages
|
|
111
|
-
const mobileMaxVisible = 3;
|
|
112
|
-
const effectiveMaxVisible = isMobile ? mobileMaxVisible : maxVisiblePages;
|
|
113
|
-
|
|
114
|
-
if (totalPages <= effectiveMaxVisible) {
|
|
115
|
-
return Array.from({ length: totalPages }, (_, i) => i + 1);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const pages: (number | 'ellipsis')[] = [];
|
|
119
|
-
const halfVisible = Math.floor(effectiveMaxVisible / 2);
|
|
120
|
-
|
|
121
|
-
if (isMobile) {
|
|
122
|
-
// Mobile: Show only current page and adjacent pages
|
|
123
|
-
if (currentPage > 1) {
|
|
124
|
-
pages.push(currentPage - 1);
|
|
125
|
-
}
|
|
126
|
-
pages.push(currentPage);
|
|
127
|
-
if (currentPage < totalPages) {
|
|
128
|
-
pages.push(currentPage + 1);
|
|
129
|
-
}
|
|
130
|
-
} else {
|
|
131
|
-
// Desktop: Full pagination logic
|
|
132
|
-
// Always show first page
|
|
133
|
-
pages.push(1);
|
|
134
|
-
|
|
135
|
-
let start = Math.max(2, currentPage - halfVisible);
|
|
136
|
-
let end = Math.min(totalPages - 1, currentPage + halfVisible);
|
|
137
|
-
|
|
138
|
-
// Adjust range if we're near the beginning or end
|
|
139
|
-
if (currentPage <= halfVisible + 1) {
|
|
140
|
-
end = Math.min(totalPages - 1, effectiveMaxVisible - 1);
|
|
141
|
-
} else if (currentPage >= totalPages - halfVisible) {
|
|
142
|
-
start = Math.max(2, totalPages - effectiveMaxVisible + 2);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// Add ellipsis after first page if needed
|
|
146
|
-
if (start > 2) {
|
|
147
|
-
pages.push('ellipsis');
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
// Add middle pages
|
|
151
|
-
for (let i = start; i <= end; i++) {
|
|
152
|
-
pages.push(i);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// Add ellipsis before last page if needed
|
|
156
|
-
if (end < totalPages - 1) {
|
|
157
|
-
pages.push('ellipsis');
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// Always show last page (if more than 1 page)
|
|
161
|
-
if (totalPages > 1) {
|
|
162
|
-
pages.push(totalPages);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
return pages;
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
const visiblePages = getVisiblePages();
|
|
170
|
-
const startItem = (currentPage - 1) * itemsPerPage + 1;
|
|
171
|
-
const endItem = Math.min(currentPage * itemsPerPage, totalItems);
|
|
172
|
-
|
|
173
|
-
const handlePageClick = (page: number) => {
|
|
174
|
-
if (page !== currentPage && page >= 1 && page <= totalPages) {
|
|
175
|
-
onPageChange(page);
|
|
176
|
-
}
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
return (
|
|
180
|
-
<div className={cn("space-y-4", className)}>
|
|
181
|
-
{/* Pagination Info */}
|
|
182
|
-
{showInfo && (
|
|
183
|
-
<div className="text-sm text-muted-foreground text-center">
|
|
184
|
-
{isMobile ? (
|
|
185
|
-
`Page ${currentPage} of ${totalPages}`
|
|
186
|
-
) : (
|
|
187
|
-
`Showing ${startItem.toLocaleString()} to ${endItem.toLocaleString()} of ${totalItems.toLocaleString()} results`
|
|
188
|
-
)}
|
|
189
|
-
</div>
|
|
190
|
-
)}
|
|
191
|
-
|
|
192
|
-
{/* Pagination Controls */}
|
|
193
|
-
<Pagination>
|
|
194
|
-
<PaginationContent>
|
|
195
|
-
{/* Previous Button */}
|
|
196
|
-
<PaginationItem>
|
|
197
|
-
<Button
|
|
198
|
-
variant="ghost"
|
|
199
|
-
size="default"
|
|
200
|
-
onClick={() => handlePageClick(currentPage - 1)}
|
|
201
|
-
disabled={!hasPreviousPage}
|
|
202
|
-
className={cn(
|
|
203
|
-
"gap-1 pl-2.5",
|
|
204
|
-
!hasPreviousPage && "pointer-events-none opacity-50"
|
|
205
|
-
)}
|
|
206
|
-
aria-label="Go to previous page"
|
|
207
|
-
>
|
|
208
|
-
<ChevronLeft className="h-4 w-4" />
|
|
209
|
-
<span>Previous</span>
|
|
210
|
-
</Button>
|
|
211
|
-
</PaginationItem>
|
|
212
|
-
|
|
213
|
-
{/* Page Numbers */}
|
|
214
|
-
{visiblePages.map((page, index) => (
|
|
215
|
-
<PaginationItem key={index}>
|
|
216
|
-
{page === 'ellipsis' ? (
|
|
217
|
-
<PaginationEllipsis />
|
|
218
|
-
) : (
|
|
219
|
-
<Button
|
|
220
|
-
variant={page === currentPage ? "outline" : "ghost"}
|
|
221
|
-
size="icon"
|
|
222
|
-
onClick={() => handlePageClick(page)}
|
|
223
|
-
aria-current={page === currentPage ? "page" : undefined}
|
|
224
|
-
className={cn(
|
|
225
|
-
page === currentPage && "pointer-events-none"
|
|
226
|
-
)}
|
|
227
|
-
>
|
|
228
|
-
{page}
|
|
229
|
-
</Button>
|
|
230
|
-
)}
|
|
231
|
-
</PaginationItem>
|
|
232
|
-
))}
|
|
233
|
-
|
|
234
|
-
{/* Next Button */}
|
|
235
|
-
<PaginationItem>
|
|
236
|
-
<Button
|
|
237
|
-
variant="ghost"
|
|
238
|
-
size="default"
|
|
239
|
-
onClick={() => handlePageClick(currentPage + 1)}
|
|
240
|
-
disabled={!hasNextPage}
|
|
241
|
-
className={cn(
|
|
242
|
-
"gap-1 pr-2.5",
|
|
243
|
-
!hasNextPage && "pointer-events-none opacity-50"
|
|
244
|
-
)}
|
|
245
|
-
aria-label="Go to next page"
|
|
246
|
-
>
|
|
247
|
-
<span>Next</span>
|
|
248
|
-
<ChevronRight className="h-4 w-4" />
|
|
249
|
-
</Button>
|
|
250
|
-
</PaginationItem>
|
|
251
|
-
</PaginationContent>
|
|
252
|
-
</Pagination>
|
|
253
|
-
</div>
|
|
254
|
-
);
|
|
255
|
-
};
|
|
256
|
-
|
|
257
|
-
StaticPagination.displayName = 'StaticPagination';
|
|
258
|
-
|
|
259
|
-
/**
|
|
260
|
-
* Hook to manage DRF pagination state
|
|
261
|
-
*
|
|
262
|
-
* Manages page and page_size state and provides methods to change them.
|
|
263
|
-
* Works seamlessly with SWR hooks that accept params.
|
|
264
|
-
*
|
|
265
|
-
* Usage:
|
|
266
|
-
* ```tsx
|
|
267
|
-
* import { useDRFPagination } from '@djangocfg/ui-nextjs';
|
|
268
|
-
* import { useMyPaginatedAPI } from './api/hooks';
|
|
269
|
-
*
|
|
270
|
-
* function MyComponent() {
|
|
271
|
-
* const pagination = useDRFPagination();
|
|
272
|
-
* const { data, isLoading } = useMyPaginatedAPI(pagination.params);
|
|
273
|
-
*
|
|
274
|
-
* return (
|
|
275
|
-
* <div>
|
|
276
|
-
* {data?.results?.map(item => <Item key={item.id} {...item} />)}
|
|
277
|
-
* <StaticPagination data={data} onPageChange={pagination.setPage} />
|
|
278
|
-
* </div>
|
|
279
|
-
* );
|
|
280
|
-
* }
|
|
281
|
-
* ```
|
|
282
|
-
*/
|
|
283
|
-
export function useDRFPagination(initialPage = 1, initialPageSize = 10) {
|
|
284
|
-
const [page, setPage] = React.useState(initialPage);
|
|
285
|
-
const [pageSize, setPageSize] = React.useState(initialPageSize);
|
|
286
|
-
|
|
287
|
-
// Reset to page 1 when page size changes
|
|
288
|
-
const handlePageSizeChange = React.useCallback((newPageSize: number) => {
|
|
289
|
-
setPageSize(newPageSize);
|
|
290
|
-
setPage(1);
|
|
291
|
-
}, []);
|
|
292
|
-
|
|
293
|
-
// Params object that can be passed directly to SWR hooks
|
|
294
|
-
const params = React.useMemo(() => ({
|
|
295
|
-
page,
|
|
296
|
-
page_size: pageSize,
|
|
297
|
-
}), [page, pageSize]);
|
|
298
|
-
|
|
299
|
-
return {
|
|
300
|
-
page,
|
|
301
|
-
pageSize,
|
|
302
|
-
setPage,
|
|
303
|
-
setPageSize: handlePageSizeChange,
|
|
304
|
-
params,
|
|
305
|
-
reset: () => {
|
|
306
|
-
setPage(initialPage);
|
|
307
|
-
setPageSize(initialPageSize);
|
|
308
|
-
},
|
|
309
|
-
};
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
/**
|
|
313
|
-
* Hook to extract pagination info from DRF response
|
|
314
|
-
*
|
|
315
|
-
* Useful when you need pagination metadata in your component logic.
|
|
316
|
-
*
|
|
317
|
-
* Usage:
|
|
318
|
-
* ```tsx
|
|
319
|
-
* const paginationInfo = useDRFPaginationInfo(data);
|
|
320
|
-
* if (paginationInfo) {
|
|
321
|
-
* console.log(`Page ${paginationInfo.currentPage} of ${paginationInfo.totalPages}`);
|
|
322
|
-
* }
|
|
323
|
-
* ```
|
|
324
|
-
*/
|
|
325
|
-
export function useDRFPaginationInfo(data?: DRFPaginatedResponse | null) {
|
|
326
|
-
return React.useMemo(() => {
|
|
327
|
-
if (!data || !('count' in data) || !('page' in data)) {
|
|
328
|
-
return null;
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
return {
|
|
332
|
-
totalItems: data.count,
|
|
333
|
-
currentPage: data.page,
|
|
334
|
-
totalPages: data.pages,
|
|
335
|
-
itemsPerPage: data.page_size,
|
|
336
|
-
hasNext: data.has_next,
|
|
337
|
-
hasPrevious: data.has_previous,
|
|
338
|
-
nextPage: data.next_page,
|
|
339
|
-
previousPage: data.previous_page,
|
|
340
|
-
results: data.results || [],
|
|
341
|
-
resultsCount: data.results?.length || 0,
|
|
342
|
-
};
|
|
343
|
-
}, [data]);
|
|
344
|
-
}
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
import { ChevronLeft, ChevronRight, MoreHorizontal } from 'lucide-react';
|
|
2
|
-
import * as React from 'react';
|
|
3
|
-
|
|
4
|
-
import { ButtonProps, Link, buttonVariants } from '@djangocfg/ui-core/components';
|
|
5
|
-
import { cn } from '@djangocfg/ui-core/lib';
|
|
6
|
-
|
|
7
|
-
const Pagination = ({ className, ...props }: React.ComponentProps<"nav">) => (
|
|
8
|
-
<nav
|
|
9
|
-
role="navigation"
|
|
10
|
-
aria-label="pagination"
|
|
11
|
-
className={cn("mx-auto flex w-full justify-center", className)}
|
|
12
|
-
{...props}
|
|
13
|
-
/>
|
|
14
|
-
)
|
|
15
|
-
Pagination.displayName = "Pagination"
|
|
16
|
-
|
|
17
|
-
const PaginationContent = React.forwardRef<
|
|
18
|
-
HTMLUListElement,
|
|
19
|
-
React.ComponentProps<"ul">
|
|
20
|
-
>(({ className, ...props }, ref) => (
|
|
21
|
-
<ul
|
|
22
|
-
ref={ref}
|
|
23
|
-
className={cn("flex flex-row items-center gap-1", className)}
|
|
24
|
-
{...props}
|
|
25
|
-
/>
|
|
26
|
-
))
|
|
27
|
-
PaginationContent.displayName = "PaginationContent"
|
|
28
|
-
|
|
29
|
-
const PaginationItem = React.forwardRef<
|
|
30
|
-
HTMLLIElement,
|
|
31
|
-
React.ComponentProps<"li"> & { key?: React.Key }
|
|
32
|
-
>(({ className, ...props }, ref) => (
|
|
33
|
-
<li ref={ref} className={cn("", className)} {...props} />
|
|
34
|
-
))
|
|
35
|
-
PaginationItem.displayName = "PaginationItem"
|
|
36
|
-
|
|
37
|
-
type PaginationLinkProps = {
|
|
38
|
-
isActive?: boolean
|
|
39
|
-
href?: string
|
|
40
|
-
} & Pick<ButtonProps, "size"> &
|
|
41
|
-
React.ComponentProps<"a">
|
|
42
|
-
|
|
43
|
-
const PaginationLink = ({
|
|
44
|
-
className,
|
|
45
|
-
isActive,
|
|
46
|
-
size = "icon",
|
|
47
|
-
href,
|
|
48
|
-
children,
|
|
49
|
-
...props
|
|
50
|
-
}: PaginationLinkProps) => {
|
|
51
|
-
const classes = cn(
|
|
52
|
-
buttonVariants({
|
|
53
|
-
variant: isActive ? "outline" : "ghost",
|
|
54
|
-
size,
|
|
55
|
-
}),
|
|
56
|
-
className
|
|
57
|
-
)
|
|
58
|
-
|
|
59
|
-
if (href) {
|
|
60
|
-
return (
|
|
61
|
-
<Link
|
|
62
|
-
href={href}
|
|
63
|
-
aria-current={isActive ? "page" : undefined}
|
|
64
|
-
className={classes}
|
|
65
|
-
>
|
|
66
|
-
{children}
|
|
67
|
-
</Link>
|
|
68
|
-
)
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return (
|
|
72
|
-
<a
|
|
73
|
-
aria-current={isActive ? "page" : undefined}
|
|
74
|
-
className={classes}
|
|
75
|
-
{...props}
|
|
76
|
-
>
|
|
77
|
-
{children}
|
|
78
|
-
</a>
|
|
79
|
-
)
|
|
80
|
-
}
|
|
81
|
-
PaginationLink.displayName = "PaginationLink"
|
|
82
|
-
|
|
83
|
-
const PaginationPrevious = ({
|
|
84
|
-
className,
|
|
85
|
-
...props
|
|
86
|
-
}: React.ComponentProps<typeof PaginationLink>) => (
|
|
87
|
-
<PaginationLink
|
|
88
|
-
aria-label="Go to previous page"
|
|
89
|
-
size="default"
|
|
90
|
-
className={cn("gap-1 pl-2.5", className)}
|
|
91
|
-
{...props}
|
|
92
|
-
>
|
|
93
|
-
<ChevronLeft className="h-4 w-4" />
|
|
94
|
-
<span>Previous</span>
|
|
95
|
-
</PaginationLink>
|
|
96
|
-
)
|
|
97
|
-
PaginationPrevious.displayName = "PaginationPrevious"
|
|
98
|
-
|
|
99
|
-
const PaginationNext = ({
|
|
100
|
-
className,
|
|
101
|
-
...props
|
|
102
|
-
}: React.ComponentProps<typeof PaginationLink>) => (
|
|
103
|
-
<PaginationLink
|
|
104
|
-
aria-label="Go to next page"
|
|
105
|
-
size="default"
|
|
106
|
-
className={cn("gap-1 pr-2.5", className)}
|
|
107
|
-
{...props}
|
|
108
|
-
>
|
|
109
|
-
<span>Next</span>
|
|
110
|
-
<ChevronRight className="h-4 w-4" />
|
|
111
|
-
</PaginationLink>
|
|
112
|
-
)
|
|
113
|
-
PaginationNext.displayName = "PaginationNext"
|
|
114
|
-
|
|
115
|
-
const PaginationEllipsis = ({
|
|
116
|
-
className,
|
|
117
|
-
...props
|
|
118
|
-
}: React.ComponentProps<"span">) => (
|
|
119
|
-
<span
|
|
120
|
-
aria-hidden
|
|
121
|
-
className={cn("flex h-9 w-9 items-center justify-center", className)}
|
|
122
|
-
{...props}
|
|
123
|
-
>
|
|
124
|
-
<MoreHorizontal className="h-4 w-4" />
|
|
125
|
-
<span className="sr-only">More pages</span>
|
|
126
|
-
</span>
|
|
127
|
-
)
|
|
128
|
-
PaginationEllipsis.displayName = "PaginationEllipsis"
|
|
129
|
-
|
|
130
|
-
export {
|
|
131
|
-
Pagination,
|
|
132
|
-
PaginationContent,
|
|
133
|
-
PaginationLink,
|
|
134
|
-
PaginationItem,
|
|
135
|
-
PaginationPrevious,
|
|
136
|
-
PaginationNext,
|
|
137
|
-
PaginationEllipsis,
|
|
138
|
-
}
|