# Pagination

## Description

A pagination controls component that provides navigation through multiple pages of content. Features customizable page numbers, navigation arrows, current page highlighting, and accessibility support for managing large datasets with efficient user navigation.

## Aliases

- Pagination
- PageNavigation
- Pager
- PageControls
- PageSelector

## Props Breakdown

**Extends:** Standalone interface (no HTML element inheritance)

| Prop | Type | Default | Required | Description |
|------|------|---------|----------|-------------|
| `className` | `string` | - | No | Additional CSS class names for custom styling |
| `currentPage` | `number` | - | No | The currently active page number |
| `totalPages` | `number` | - | No | Total number of pages available |
| `updateCurrentPage` | `(page: number) => void` | - | No | Callback function when page changes |
| `previousPageIcon` | `ReactNode` | - | No | Custom icon for previous page button |
| `nextPageIcon` | `ReactNode` | - | No | Custom icon for next page button |

## Examples

### Basic Usage
```tsx
import { Pagination } from '@delightui/components';

function BasicExample() {
  const [currentPage, setCurrentPage] = useState(1);
  const totalPages = 10;

  return (
    <Pagination
      currentPage={currentPage}
      totalPages={totalPages}
      updateCurrentPage={setCurrentPage}
    />
  );
}
```

### Custom Navigation Icons
```tsx
function CustomIconsExample() {
  const [currentPage, setCurrentPage] = useState(1);
  const totalPages = 15;

  return (
    <Pagination
      currentPage={currentPage}
      totalPages={totalPages}
      updateCurrentPage={setCurrentPage}
      previousPageIcon={<Icon icon="ChevronLeft" />}
      nextPageIcon={<Icon icon="ChevronRight" />}
    />
  );
}
```

### Table Pagination
```tsx
function TablePaginationExample() {
  const [currentPage, setCurrentPage] = useState(1);
  const [itemsPerPage, setItemsPerPage] = useState(10);
  
  // Mock data
  const totalItems = 247;
  const totalPages = Math.ceil(totalItems / itemsPerPage);
  const startItem = (currentPage - 1) * itemsPerPage + 1;
  const endItem = Math.min(currentPage * itemsPerPage, totalItems);

  const mockData = Array.from({ length: itemsPerPage }, (_, index) => ({
    id: startItem + index,
    name: `Item ${startItem + index}`,
    status: ['Active', 'Inactive', 'Pending'][Math.floor(Math.random() * 3)]
  }));

  return (
    <div className="table-pagination-example">
      <Table>
        <TableHeader>
          <TableHeaderCell>ID</TableHeaderCell>
          <TableHeaderCell>Name</TableHeaderCell>
          <TableHeaderCell>Status</TableHeaderCell>
        </TableHeader>
        <TableBody>
          {mockData.map(item => (
            <TableRow key={item.id}>
              <TableCell>{item.id}</TableCell>
              <TableCell>{item.name}</TableCell>
              <TableCell>
                <Chip size="Small" style={item.status === 'Active' ? 'Success' : 'Default'}>
                  {item.status}
                </Chip>
              </TableCell>
            </TableRow>
          ))}
        </TableBody>
      </Table>

      <div className="pagination-info">
        <Text type="BodySmall">
          Showing {startItem}-{endItem} of {totalItems} items
        </Text>
        
        <Select value={itemsPerPage} onValueChange={setItemsPerPage}>
          <Option value={5}>5 per page</Option>
          <Option value={10}>10 per page</Option>
          <Option value={25}>25 per page</Option>
          <Option value={50}>50 per page</Option>
        </Select>
      </div>

      <Pagination
        currentPage={currentPage}
        totalPages={totalPages}
        updateCurrentPage={setCurrentPage}
        className="table-pagination"
      />
    </div>
  );
}
```

### Search Results Pagination
```tsx
function SearchResultsPaginationExample() {
  const [currentPage, setCurrentPage] = useState(1);
  const [searchTerm, setSearchTerm] = useState('react');
  
  // Mock search results
  const resultsPerPage = 8;
  const totalResults = 156;
  const totalPages = Math.ceil(totalResults / resultsPerPage);

  const mockResults = Array.from({ length: resultsPerPage }, (_, index) => ({
    id: (currentPage - 1) * resultsPerPage + index + 1,
    title: `${searchTerm} Tutorial ${(currentPage - 1) * resultsPerPage + index + 1}`,
    description: 'Learn advanced techniques and best practices...',
    category: ['Tutorial', 'Guide', 'Documentation'][Math.floor(Math.random() * 3)]
  }));

  return (
    <div className="search-results-pagination">
      <div className="search-header">
        <Input 
          placeholder="Search..."
          value={searchTerm}
          onValueChange={setSearchTerm}
          leadingIcon={<Icon icon="Search" />}
        />
        
        <Text type="BodySmall">
          {totalResults} results found for "{searchTerm}"
        </Text>
      </div>

      <div className="search-results">
        {mockResults.map(result => (
          <Card key={result.id} className="search-result-card">
            <div className="result-header">
              <Text type="Heading6">{result.title}</Text>
              <Chip size="Small">{result.category}</Chip>
            </div>
            <Text type="BodyMedium">{result.description}</Text>
            <Button type="Ghost" size="Small">
              Read More
            </Button>
          </Card>
        ))}
      </div>

      <Pagination
        currentPage={currentPage}
        totalPages={totalPages}
        updateCurrentPage={setCurrentPage}
        className="search-pagination"
      />
    </div>
  );
}
```

### Blog Post Pagination
```tsx
function BlogPaginationExample() {
  const [currentPage, setCurrentPage] = useState(1);
  const postsPerPage = 5;
  const totalPosts = 42;
  const totalPages = Math.ceil(totalPosts / postsPerPage);

  const mockPosts = Array.from({ length: postsPerPage }, (_, index) => ({
    id: (currentPage - 1) * postsPerPage + index + 1,
    title: `Blog Post Title ${(currentPage - 1) * postsPerPage + index + 1}`,
    excerpt: 'This is a brief excerpt of the blog post content...',
    author: 'John Doe',
    date: '2024-01-15',
    readTime: '5 min read'
  }));

  return (
    <div className="blog-pagination">
      <div className="blog-posts">
        {mockPosts.map(post => (
          <Card key={post.id} className="blog-post-card">
            <Text type="Heading5">{post.title}</Text>
            <Text type="BodyMedium">{post.excerpt}</Text>
            
            <div className="post-meta">
              <div className="author-info">
                <Icon icon="Person" />
                <Text type="BodySmall">{post.author}</Text>
              </div>
              
              <div className="post-date">
                <Icon icon="Calendar" />
                <Text type="BodySmall">{post.date}</Text>
              </div>
              
              <div className="read-time">
                <Icon icon="Schedule" />
                <Text type="BodySmall">{post.readTime}</Text>
              </div>
            </div>
            
            <Button type="Outlined" size="Small">
              Read More
            </Button>
          </Card>
        ))}
      </div>

      <div className="blog-pagination-controls">
        <Pagination
          currentPage={currentPage}
          totalPages={totalPages}
          updateCurrentPage={setCurrentPage}
          previousPageIcon={<Icon icon="ArrowBack" />}
          nextPageIcon={<Icon icon="ArrowForward" />}
        />
        
        <Text type="BodySmall" className="pagination-info">
          Page {currentPage} of {totalPages}
        </Text>
      </div>
    </div>
  );
}
```

### E-commerce Product Pagination
```tsx
function ProductPaginationExample() {
  const [currentPage, setCurrentPage] = useState(1);
  const [sortBy, setSortBy] = useState('name');
  const [filterCategory, setFilterCategory] = useState('all');
  
  const productsPerPage = 12;
  const totalProducts = 89;
  const totalPages = Math.ceil(totalProducts / productsPerPage);

  const mockProducts = Array.from({ length: productsPerPage }, (_, index) => ({
    id: (currentPage - 1) * productsPerPage + index + 1,
    name: `Product ${(currentPage - 1) * productsPerPage + index + 1}`,
    price: (Math.random() * 100 + 10).toFixed(2),
    category: ['Electronics', 'Clothing', 'Books'][Math.floor(Math.random() * 3)],
    rating: (Math.random() * 2 + 3).toFixed(1),
    image: `/product-${(currentPage - 1) * productsPerPage + index + 1}.jpg`
  }));

  return (
    <div className="product-pagination">
      <div className="product-filters">
        <Select value={filterCategory} onValueChange={setFilterCategory}>
          <Option value="all">All Categories</Option>
          <Option value="electronics">Electronics</Option>
          <Option value="clothing">Clothing</Option>
          <Option value="books">Books</Option>
        </Select>
        
        <Select value={sortBy} onValueChange={setSortBy}>
          <Option value="name">Sort by Name</Option>
          <Option value="price">Sort by Price</Option>
          <Option value="rating">Sort by Rating</Option>
        </Select>
        
        <Text type="BodySmall">
          {totalProducts} products found
        </Text>
      </div>

      <div className="product-grid">
        {mockProducts.map(product => (
          <Card key={product.id} className="product-card">
            <Image src={product.image} alt={product.name} />
            <Text type="Heading6">{product.name}</Text>
            <Text type="BodyMedium">${product.price}</Text>
            <div className="product-rating">
              <Icon icon="Star" />
              <Text type="BodySmall">{product.rating}</Text>
            </div>
            <Button type="Filled" size="Small">
              Add to Cart
            </Button>
          </Card>
        ))}
      </div>

      <Pagination
        currentPage={currentPage}
        totalPages={totalPages}
        updateCurrentPage={setCurrentPage}
        className="product-pagination-controls"
      />
    </div>
  );
}
```

### Advanced Pagination with Jump
```tsx
function AdvancedPaginationExample() {
  const [currentPage, setCurrentPage] = useState(1);
  const [goToPage, setGoToPage] = useState('');
  const totalPages = 25;

  const handleGoToPage = () => {
    const pageNumber = parseInt(goToPage);
    if (pageNumber >= 1 && pageNumber <= totalPages) {
      setCurrentPage(pageNumber);
      setGoToPage('');
    }
  };

  const handleKeyPress = (event) => {
    if (event.key === 'Enter') {
      handleGoToPage();
    }
  };

  return (
    <div className="advanced-pagination">
      <div className="pagination-controls">
        <Pagination
          currentPage={currentPage}
          totalPages={totalPages}
          updateCurrentPage={setCurrentPage}
          previousPageIcon={<Icon icon="SkipPrevious" />}
          nextPageIcon={<Icon icon="SkipNext" />}
        />
      </div>

      <div className="pagination-extras">
        <div className="page-jump">
          <Text type="BodySmall">Go to page:</Text>
          <Input
            value={goToPage}
            onValueChange={setGoToPage}
            onKeyPress={handleKeyPress}
            placeholder="Page #"
            size="Small"
            style={{ width: '80px' }}
          />
          <Button 
            onClick={handleGoToPage}
            disabled={!goToPage}
            size="Small"
          >
            Go
          </Button>
        </div>
        
        <div className="pagination-info">
          <Text type="BodySmall">
            Page {currentPage} of {totalPages}
          </Text>
        </div>
      </div>
    </div>
  );
}
```

### Infinite Scroll Alternative
```tsx
function InfiniteScrollExample() {
  const [currentPage, setCurrentPage] = useState(1);
  const [loadingMore, setLoadingMore] = useState(false);
  const [showPagination, setShowPagination] = useState(false);
  
  const itemsPerPage = 10;
  const totalPages = 20;
  const [loadedItems, setLoadedItems] = useState([]);

  const loadMoreItems = async () => {
    setLoadingMore(true);
    
    // Simulate API call
    await new Promise(resolve => setTimeout(resolve, 1000));
    
    const newItems = Array.from({ length: itemsPerPage }, (_, index) => ({
      id: loadedItems.length + index + 1,
      title: `Item ${loadedItems.length + index + 1}`,
      content: 'This is the content for this item...'
    }));
    
    setLoadedItems(prev => [...prev, ...newItems]);
    setCurrentPage(prev => prev + 1);
    setLoadingMore(false);
  };

  return (
    <div className="infinite-scroll-example">
      <div className="scroll-toggle">
        <Toggle 
          checked={showPagination}
          onCheckedChange={setShowPagination}
          label="Use pagination instead of infinite scroll"
        />
      </div>

      <div className="items-list">
        {loadedItems.map(item => (
          <Card key={item.id} className="list-item">
            <Text type="Heading6">{item.title}</Text>
            <Text type="BodyMedium">{item.content}</Text>
          </Card>
        ))}
      </div>

      {showPagination ? (
        <Pagination
          currentPage={currentPage}
          totalPages={totalPages}
          updateCurrentPage={setCurrentPage}
        />
      ) : (
        <div className="load-more-section">
          <Button 
            onClick={loadMoreItems}
            loading={loadingMore}
            disabled={currentPage >= totalPages}
            type="Outlined"
          >
            {loadingMore ? 'Loading...' : 'Load More Items'}
          </Button>
          
          {currentPage >= totalPages && (
            <Text type="BodySmall">
              All items loaded ({loadedItems.length} total)
            </Text>
          )}
        </div>
      )}
    </div>
  );
}
```

### Responsive Pagination
```tsx
function ResponsivePaginationExample() {
  const [currentPage, setCurrentPage] = useState(1);
  const [isMobile, setIsMobile] = useState(false);
  const totalPages = 15;

  useEffect(() => {
    const checkMobile = () => {
      setIsMobile(window.innerWidth < 768);
    };
    
    checkMobile();
    window.addEventListener('resize', checkMobile);
    
    return () => window.removeEventListener('resize', checkMobile);
  }, []);

  return (
    <div className="responsive-pagination">
      <div className="content-area">
        <Text type="Heading4">
          Page {currentPage} Content
        </Text>
        <Text type="BodyMedium">
          This content changes based on the selected page.
        </Text>
      </div>

      {isMobile ? (
        <div className="mobile-pagination">
          <Button 
            disabled={currentPage === 1}
            onClick={() => setCurrentPage(currentPage - 1)}
            leadingIcon={<Icon icon="ChevronLeft" />}
          >
            Previous
          </Button>
          
          <Text type="BodyMedium">
            {currentPage} / {totalPages}
          </Text>
          
          <Button 
            disabled={currentPage === totalPages}
            onClick={() => setCurrentPage(currentPage + 1)}
            trailingIcon={<Icon icon="ChevronRight" />}
          >
            Next
          </Button>
        </div>
      ) : (
        <Pagination
          currentPage={currentPage}
          totalPages={totalPages}
          updateCurrentPage={setCurrentPage}
          className="desktop-pagination"
        />
      )}
    </div>
  );
}
```

### Pagination with Loading States
```tsx
function LoadingPaginationExample() {
  const [currentPage, setCurrentPage] = useState(1);
  const [isLoading, setIsLoading] = useState(false);
  const [data, setData] = useState([]);
  const totalPages = 12;

  const fetchPageData = async (page) => {
    setIsLoading(true);
    
    // Simulate API call
    await new Promise(resolve => setTimeout(resolve, 1500));
    
    const pageData = Array.from({ length: 8 }, (_, index) => ({
      id: (page - 1) * 8 + index + 1,
      title: `Page ${page} - Item ${index + 1}`,
      content: 'Loading content from server...'
    }));
    
    setData(pageData);
    setIsLoading(false);
  };

  const handlePageChange = (page) => {
    setCurrentPage(page);
    fetchPageData(page);
  };

  useEffect(() => {
    fetchPageData(1);
  }, []);

  return (
    <div className="loading-pagination">
      <div className="data-container">
        {isLoading ? (
          <div className="loading-state">
            <Spinner size="Large" />
            <Text type="BodyMedium">Loading page data...</Text>
          </div>
        ) : (
          <div className="data-grid">
            {data.map(item => (
              <Card key={item.id} className="data-item">
                <Text type="Heading6">{item.title}</Text>
                <Text type="BodyMedium">{item.content}</Text>
              </Card>
            ))}
          </div>
        )}
      </div>

      <Pagination
        currentPage={currentPage}
        totalPages={totalPages}
        updateCurrentPage={handlePageChange}
        className={isLoading ? 'disabled' : ''}
      />
    </div>
  );
}
```