@djangocfg/ui-nextjs 2.1.320 → 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,214 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { usePathname } from 'next/navigation';
|
|
4
|
-
import React from 'react';
|
|
5
|
-
|
|
6
|
-
import { useIsMobile } from '@djangocfg/ui-core/hooks';
|
|
7
|
-
import { cn } from '@djangocfg/ui-core/lib';
|
|
8
|
-
|
|
9
|
-
import { useQueryParams } from '@djangocfg/api/auth';
|
|
10
|
-
|
|
11
|
-
import {
|
|
12
|
-
Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink,
|
|
13
|
-
PaginationNext, PaginationPrevious
|
|
14
|
-
} from './pagination';
|
|
15
|
-
|
|
16
|
-
interface SSRPaginationProps {
|
|
17
|
-
currentPage: number;
|
|
18
|
-
totalPages: number;
|
|
19
|
-
totalItems: number;
|
|
20
|
-
itemsPerPage: number;
|
|
21
|
-
hasNextPage: boolean;
|
|
22
|
-
hasPreviousPage: boolean;
|
|
23
|
-
className?: string;
|
|
24
|
-
showInfo?: boolean;
|
|
25
|
-
maxVisiblePages?: number;
|
|
26
|
-
baseUrl?: string;
|
|
27
|
-
pathname?: string;
|
|
28
|
-
preserveQuery?: boolean;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export const SSRPagination: React.FC<SSRPaginationProps> = ({
|
|
32
|
-
currentPage,
|
|
33
|
-
totalPages,
|
|
34
|
-
totalItems,
|
|
35
|
-
itemsPerPage,
|
|
36
|
-
hasNextPage,
|
|
37
|
-
hasPreviousPage: _hasPreviousPage,
|
|
38
|
-
className,
|
|
39
|
-
showInfo = true,
|
|
40
|
-
maxVisiblePages = 7,
|
|
41
|
-
baseUrl,
|
|
42
|
-
pathname: propPathname,
|
|
43
|
-
preserveQuery = true,
|
|
44
|
-
}) => {
|
|
45
|
-
const queryParams = useQueryParams();
|
|
46
|
-
const pathname = usePathname();
|
|
47
|
-
const isMobile = useIsMobile();
|
|
48
|
-
|
|
49
|
-
// Get current page from URL if available, otherwise use prop
|
|
50
|
-
const getCurrentPageFromUrl = (): number => {
|
|
51
|
-
const pageParam = queryParams.get('page');
|
|
52
|
-
if (pageParam) {
|
|
53
|
-
const pageNum = parseInt(pageParam, 10);
|
|
54
|
-
return isNaN(pageNum) ? 1 : pageNum;
|
|
55
|
-
}
|
|
56
|
-
return 1;
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
const actualCurrentPage = getCurrentPageFromUrl() || currentPage;
|
|
60
|
-
|
|
61
|
-
// Calculate actual navigation state based on current page from URL
|
|
62
|
-
const actualHasPreviousPage = actualCurrentPage > 1;
|
|
63
|
-
|
|
64
|
-
// actualHasNextPage kept for clarity, even though it equals hasNextPage
|
|
65
|
-
// @ts-ignore reserved for future use
|
|
66
|
-
const _actualHasNextPage = hasNextPage;
|
|
67
|
-
|
|
68
|
-
// Generate URL for a specific page
|
|
69
|
-
const getPageUrl = (page: number): string => {
|
|
70
|
-
if (baseUrl) {
|
|
71
|
-
return `${baseUrl}?page=${page}`;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Use current route with updated page parameter
|
|
75
|
-
const newSearchParams = preserveQuery
|
|
76
|
-
? new URLSearchParams(queryParams.toString())
|
|
77
|
-
: new URLSearchParams();
|
|
78
|
-
|
|
79
|
-
newSearchParams.set('page', page.toString());
|
|
80
|
-
|
|
81
|
-
// Remove page=1 from URL to keep URLs clean
|
|
82
|
-
if (page === 1) {
|
|
83
|
-
newSearchParams.delete('page');
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const queryString = newSearchParams.toString();
|
|
87
|
-
const basePath = propPathname || pathname || '';
|
|
88
|
-
return queryString ? `${basePath}?${queryString}` : basePath;
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
// Generate array of page numbers to display
|
|
92
|
-
const getVisiblePages = (): (number | 'ellipsis')[] => {
|
|
93
|
-
// On mobile, show fewer pages
|
|
94
|
-
const mobileMaxVisible = 3;
|
|
95
|
-
const effectiveMaxVisible = isMobile ? mobileMaxVisible : maxVisiblePages;
|
|
96
|
-
|
|
97
|
-
if (totalPages <= effectiveMaxVisible) {
|
|
98
|
-
return Array.from({ length: totalPages }, (_, i) => i + 1);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const pages: (number | 'ellipsis')[] = [];
|
|
102
|
-
const halfVisible = Math.floor(effectiveMaxVisible / 2);
|
|
103
|
-
|
|
104
|
-
if (isMobile) {
|
|
105
|
-
// Mobile: Show only current page and adjacent pages
|
|
106
|
-
if (actualCurrentPage > 1) {
|
|
107
|
-
pages.push(actualCurrentPage - 1);
|
|
108
|
-
}
|
|
109
|
-
pages.push(actualCurrentPage);
|
|
110
|
-
if (actualCurrentPage < totalPages) {
|
|
111
|
-
pages.push(actualCurrentPage + 1);
|
|
112
|
-
}
|
|
113
|
-
} else {
|
|
114
|
-
// Desktop: Full pagination logic
|
|
115
|
-
// Always show first page
|
|
116
|
-
pages.push(1);
|
|
117
|
-
|
|
118
|
-
let start = Math.max(2, actualCurrentPage - halfVisible);
|
|
119
|
-
let end = Math.min(totalPages - 1, actualCurrentPage + halfVisible);
|
|
120
|
-
|
|
121
|
-
// Adjust range if we're near the beginning or end
|
|
122
|
-
if (actualCurrentPage <= halfVisible + 1) {
|
|
123
|
-
end = Math.min(totalPages - 1, effectiveMaxVisible - 1);
|
|
124
|
-
} else if (actualCurrentPage >= totalPages - halfVisible) {
|
|
125
|
-
start = Math.max(2, totalPages - effectiveMaxVisible + 2);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// Add ellipsis after first page if needed
|
|
129
|
-
if (start > 2) {
|
|
130
|
-
pages.push('ellipsis');
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// Add middle pages
|
|
134
|
-
for (let i = start; i <= end; i++) {
|
|
135
|
-
pages.push(i);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// Add ellipsis before last page if needed
|
|
139
|
-
if (end < totalPages - 1) {
|
|
140
|
-
pages.push('ellipsis');
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// Always show last page (if more than 1 page)
|
|
144
|
-
if (totalPages > 1) {
|
|
145
|
-
pages.push(totalPages);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
return pages;
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
const visiblePages = getVisiblePages();
|
|
153
|
-
const startItem = (actualCurrentPage - 1) * itemsPerPage + 1;
|
|
154
|
-
const endItem = Math.min(actualCurrentPage * itemsPerPage, totalItems);
|
|
155
|
-
|
|
156
|
-
// Don't render if no items
|
|
157
|
-
if (totalItems === 0) {
|
|
158
|
-
return null;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
return (
|
|
162
|
-
<div className={cn("space-y-4", className)}>
|
|
163
|
-
{/* Pagination Info */}
|
|
164
|
-
{showInfo && (
|
|
165
|
-
<div className="text-sm text-muted-foreground text-center">
|
|
166
|
-
{isMobile ? (
|
|
167
|
-
`Page ${actualCurrentPage} of ${totalPages}`
|
|
168
|
-
) : (
|
|
169
|
-
`Showing ${startItem.toLocaleString()} to ${endItem.toLocaleString()} of ${totalItems.toLocaleString()} results`
|
|
170
|
-
)}
|
|
171
|
-
</div>
|
|
172
|
-
)}
|
|
173
|
-
|
|
174
|
-
{/* Pagination Controls */}
|
|
175
|
-
<Pagination>
|
|
176
|
-
<PaginationContent>
|
|
177
|
-
{/* Previous Button */}
|
|
178
|
-
<PaginationItem>
|
|
179
|
-
<PaginationPrevious
|
|
180
|
-
href={actualHasPreviousPage ? getPageUrl(actualCurrentPage - 1) : undefined}
|
|
181
|
-
className={!actualHasPreviousPage ? "pointer-events-none opacity-50" : undefined}
|
|
182
|
-
/>
|
|
183
|
-
</PaginationItem>
|
|
184
|
-
|
|
185
|
-
{/* Page Numbers */}
|
|
186
|
-
{visiblePages.map((page, index) => (
|
|
187
|
-
<PaginationItem key={index}>
|
|
188
|
-
{page === 'ellipsis' ? (
|
|
189
|
-
<PaginationEllipsis />
|
|
190
|
-
) : (
|
|
191
|
-
<PaginationLink
|
|
192
|
-
href={getPageUrl(page)}
|
|
193
|
-
isActive={page === actualCurrentPage}
|
|
194
|
-
>
|
|
195
|
-
{page}
|
|
196
|
-
</PaginationLink>
|
|
197
|
-
)}
|
|
198
|
-
</PaginationItem>
|
|
199
|
-
))}
|
|
200
|
-
|
|
201
|
-
{/* Next Button */}
|
|
202
|
-
<PaginationItem>
|
|
203
|
-
<PaginationNext
|
|
204
|
-
href={hasNextPage ? getPageUrl(actualCurrentPage + 1) : undefined}
|
|
205
|
-
className={!hasNextPage ? "pointer-events-none opacity-50" : undefined}
|
|
206
|
-
/>
|
|
207
|
-
</PaginationItem>
|
|
208
|
-
</PaginationContent>
|
|
209
|
-
</Pagination>
|
|
210
|
-
</div>
|
|
211
|
-
);
|
|
212
|
-
};
|
|
213
|
-
|
|
214
|
-
SSRPagination.displayName = 'SSRPagination';
|