A powerful, customizable pagination component for React applications with TypeScript support. Features traditional pagination, infinite scroll, animations, and extensive customization options.
npm install @aniruddha1806/paginator
- 📄 Traditional pagination with page numbers
- 🔄 Infinite scroll support with load more functionality
- 🎭 Animated transitions (slide, zoom effects)
- 🎯 Jump to page functionality
- 🎨 Extensive styling customization
- 📱 Responsive design with ellipsis for large page ranges
- 🔢 Item count and range display
- ♿ Accessibility features with ARIA support
- 🎛️ Customizable labels and buttons
- 📝 TypeScript support with full type definitions
- 🪶 Zero dependencies and lightweight
import Paginator from '@aniruddha1806/paginator';
function App() {
const [currentPage, setCurrentPage] = useState(1);
const totalPages = 10;
return (
<Paginator
totalPages={totalPages}
currentPage={currentPage}
onPageChange={setCurrentPage}
/>
);
}
Prop | Type | Default | Description |
---|---|---|---|
totalPages |
number |
required |
Total number of pages |
currentPage |
number |
required |
Current active page (1-indexed) |
onPageChange |
(page: number) => void |
required |
Page change callback |
maxVisiblePages |
number |
5 |
Maximum visible page buttons |
Prop | Type | Default | Description |
---|---|---|---|
className |
string |
undefined |
CSS class for container |
buttonClassName |
string |
undefined |
CSS class for page buttons |
activeButtonClassName |
string |
undefined |
CSS class for active button |
disabledButtonClassName |
string |
undefined |
CSS class for disabled buttons |
prevNextButtonClassName |
string |
undefined |
CSS class for prev/next buttons |
Prop | Type | Default | Description |
---|---|---|---|
prevLabel |
React.ReactNode |
"Previous" |
Previous button label |
nextLabel |
React.ReactNode |
"Next" |
Next button label |
firstLabel |
React.ReactNode |
"First" |
First button label |
lastLabel |
React.ReactNode |
"Last" |
Last button label |
showFirstLast |
boolean |
false |
Show first/last buttons |
Prop | Type | Default | Description |
---|---|---|---|
showJumpToPage |
boolean |
false |
Show jump to page input |
animateTransitions |
boolean |
false |
Enable page transition animations |
animationType |
"slide" | "zoom" |
"slide" |
Animation type |
Prop | Type | Default | Description |
---|---|---|---|
infiniteScroll |
boolean |
false |
Enable infinite scroll mode |
onLoadMore |
() => void |
undefined |
Load more callback |
hasMoreItems |
boolean |
true |
Whether more items are available |
loadingLabel |
React.ReactNode |
"Loading more..." |
Loading indicator text |
itemsPerBatch |
number |
10 |
Items loaded per batch |
totalItems |
number |
undefined |
Total number of items |
Simple pagination with default styling:
import { useState } from 'react';
import Paginator from '@aniruddha1806/paginator';
function BasicPaginationExample() {
const [currentPage, setCurrentPage] = useState(1);
const [data, setData] = useState([]);
const itemsPerPage = 10;
const totalItems = 100;
const totalPages = Math.ceil(totalItems / itemsPerPage);
// Simulate data loading
const loadData = (page) => {
const start = (page - 1) * itemsPerPage;
const end = start + itemsPerPage;
const newData = Array.from({ length: itemsPerPage }, (_, i) => ({
id: start + i + 1,
name: `Item ${start + i + 1}`
}));
setData(newData);
};
const handlePageChange = (page) => {
setCurrentPage(page);
loadData(page);
};
return (
<div>
<div style={{ minHeight: '400px', padding: '20px' }}>
<h3>Items {((currentPage - 1) * itemsPerPage) + 1} - {Math.min(currentPage * itemsPerPage, totalItems)}</h3>
<ul>
{data.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
</div>
<Paginator
totalPages={totalPages}
currentPage={currentPage}
onPageChange={handlePageChange}
/>
</div>
);
}
Full-featured pagination with animations and jump functionality:
import { useState } from 'react';
import Paginator from '@aniruddha1806/paginator';
function AdvancedPaginationExample() {
const [currentPage, setCurrentPage] = useState(1);
const totalPages = 20;
return (
<div style={{ padding: '20px' }}>
<h3>Advanced Pagination</h3>
<Paginator
totalPages={totalPages}
currentPage={currentPage}
onPageChange={setCurrentPage}
maxVisiblePages={7}
showFirstLast={true}
showJumpToPage={true}
animateTransitions={true}
animationType="slide"
prevLabel="← Prev"
nextLabel="Next →"
firstLabel="⇤ First"
lastLabel="Last ⇥"
/>
<div style={{
marginTop: '20px',
padding: '16px',
backgroundColor: '#f8f9fa',
borderRadius: '8px'
}}>
<p><strong>Current Page:</strong> {currentPage}</p>
<p><strong>Total Pages:</strong> {totalPages}</p>
</div>
</div>
);
}
Apply custom styling with CSS classes:
import Paginator from '@aniruddha1806/paginator';
import './custom-pagination.css'; // Your custom CSS
function CustomStyledExample() {
const [currentPage, setCurrentPage] = useState(1);
return (
<Paginator
totalPages={15}
currentPage={currentPage}
onPageChange={setCurrentPage}
className="custom-paginator"
buttonClassName="custom-button"
activeButtonClassName="custom-active"
disabledButtonClassName="custom-disabled"
prevNextButtonClassName="custom-nav-button"
/>
);
}
CSS file (custom-pagination.css):
.custom-paginator {
display: flex;
justify-content: center;
align-items: center;
gap: 8px;
padding: 20px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 12px;
box-shadow: 0 4px 15px rgba(0,0,0,0.1);
}
.custom-button {
min-width: 40px;
height: 40px;
border-radius: 8px;
border: 2px solid rgba(255,255,255,0.3);
background: rgba(255,255,255,0.1);
color: white;
font-weight: 600;
transition: all 0.3s ease;
}
.custom-button:hover {
background: rgba(255,255,255,0.2);
transform: translateY(-2px);
}
.custom-active {
background: rgba(255,255,255,0.9);
color: #667eea;
border-color: rgba(255,255,255,0.9);
}
.custom-disabled {
opacity: 0.4;
cursor: not-allowed;
}
.custom-nav-button {
padding: 0 16px;
border-radius: 20px;
}
Implement infinite scrolling for large datasets:
import { useState, useEffect } from 'react';
import Paginator from '@aniruddha1806/paginator';
function InfiniteScrollExample() {
const [items, setItems] = useState([]);
const [hasMore, setHasMore] = useState(true);
const [loading, setLoading] = useState(false);
// Simulate initial data load
useEffect(() => {
loadInitialData();
}, []);
const loadInitialData = () => {
const initialItems = Array.from({ length: 20 }, (_, i) => ({
id: i + 1,
title: `Item ${i + 1}`,
description: `Description for item ${i + 1}`
}));
setItems(initialItems);
};
const loadMore = async () => {
if (loading) return;
setLoading(true);
// Simulate API call delay
await new Promise(resolve => setTimeout(resolve, 1000));
const currentLength = items.length;
const newItems = Array.from({ length: 10 }, (_, i) => ({
id: currentLength + i + 1,
title: `Item ${currentLength + i + 1}`,
description: `Description for item ${currentLength + i + 1}`
}));
setItems(prev => [...prev, ...newItems]);
setLoading(false);
// Stop loading more after 100 items
if (items.length + newItems.length >= 100) {
setHasMore(false);
}
};
return (
<div style={{ maxWidth: '600px', margin: '0 auto', padding: '20px' }}>
<h2>Infinite Scroll Example</h2>
<div style={{ marginBottom: '20px' }}>
{items.map(item => (
<div
key={item.id}
style={{
padding: '16px',
margin: '8px 0',
border: '1px solid #e9ecef',
borderRadius: '8px',
backgroundColor: '#f8f9fa'
}}
>
<h4 style={{ margin: '0 0 8px 0' }}>{item.title}</h4>
<p style={{ margin: 0, color: '#666' }}>{item.description}</p>
</div>
))}
</div>
<Paginator
infiniteScroll={true}
onLoadMore={loadMore}
hasMoreItems={hasMore}
loadingLabel={loading ? "Loading..." : "Load more items"}
totalPages={0}
currentPage={1}
onPageChange={() => {}}
/>
<div style={{
textAlign: 'center',
marginTop: '20px',
color: '#666',
fontSize: '14px'
}}>
Loaded {items.length} items
</div>
</div>
);
}
The component provides full TypeScript support:
import Paginator, { PaginatorProps } from '@aniruddha1806/paginator';
import { useState, useCallback } from 'react';
interface PaginatedData<T> {
items: T[];
totalPages: number;
currentPage: number;
totalItems: number;
}
interface User {
id: number;
name: string;
email: string;
}
const PaginatedUserList: React.FC = () => {
const [paginatedData, setPaginatedData] = useState<PaginatedData<User>>({
items: [],
totalPages: 0,
currentPage: 1,
totalItems: 0
});
const handlePageChange = useCallback((page: number): void => {
// Fetch data for the new page
fetchUsersForPage(page);
}, []);
const fetchUsersForPage = async (page: number): Promise<void> => {
try {
const response = await fetch(`/api/users?page=${page}`);
const data = await response.json();
setPaginatedData(data);
} catch (error) {
console.error('Error fetching users:', error);
}
};
const paginatorProps: PaginatorProps = {
totalPages: paginatedData.totalPages,
currentPage: paginatedData.currentPage,
onPageChange: handlePageChange,
maxVisiblePages: 7,
showJumpToPage: true,
animateTransitions: true,
totalItems: paginatedData.totalItems,
itemsPerBatch: 10
};
return (
<div>
<div>
{paginatedData.items.map(user => (
<div key={user.id}>
<h3>{user.name}</h3>
<p>{user.email}</p>
</div>
))}
</div>
<Paginator {...paginatorProps} />
</div>
);
};