Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@ajna/pagination

Package Overview
Dependencies
Maintainers
1
Versions
21
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ajna/pagination

## Table of Contents

  • 1.4.1
  • Source
  • npm
  • Socket score

Version published
Maintainers
1
Created
Source

@ajna/pagination

Table of Contents

Version

npm version


Installation

npm

npm i chakra-paginator

Yarn

yarn add chakra-paginator

Demo with all options applied

Check it out in this Sandbox


Components


Pagination

PropDescriptionTypeDefaultRequired
pagesCountThe total number of pagesnumberyes
currentPageThe page which is currently being selectednumberyes
onPageChangeOn change handler which returns the last selected page(currentPage: number) => voidyes
isDisabledDenotates if all items on the pagination are disabled or notbooleanfalseno

PaginationContainer

PaginationContainer is a _Flex_ component, so any _FlexProps_ are accepted

PaginationPageGroup

PaginationPageGroup is a _Stack_ component, so any _StackProps_ are accepted

PaginationPrevious

PaginationPrevious is a _Button_ component, so any _ButtonProps_ are accepted

PaginationNext

PaginationNext is a _Button_ component, so any _ButtonProps_ are accepted

PaginationPage

PaginationPage is a _Button_ component, so any _ButtonProps_ are accepted

PaginationSeparator

PaginationSeparator is a _Button_ component, so any _ButtonProps_ are accepted

Hooks

usePagination


Options
PropDescriptionTypeDefaultRequired
initialStateInitial states for pagination valuesInitialStateyes
totalThe total amount of items from the endpoint you are consumingnumberundefinedno
limitsThe limits cut the amount of pages to showLimitsundefinedno
pagesCountIf the amount of pages is manually set, it will take precedencenumberundefinedno

Returned values
PropDescriptionTypeDefault
offsetOffset value generatednumber0
pagesThe array of pages to rendernumber[][]
pagesCountThe total amount of pagesnumber0
currentPageThe page which is currently being selectednumber
pageSizeThe amount of items per pagenumberundefined
isDisabledDenotates if all items on the pagination are disabled or notbooleanfalse
setPageSizeA setter for the isDisabled valueDispatch<SetStateAction>
setIsDisabledA setter for the isDisabled valueDispatch<SetStateAction>
setCurrentPageA setter for the currentPage valueDispatch<SetStateAction>

Usage


Minimal

This is the bare minimum set up you need to get it up and working
import React, { FC, ChangeEvent, useEffect, useState } from "react";
import { ChakraProvider } from "@chakra-ui/react";
import {
  Paginator,
  Container,
  Previous,
  Next,
  PageGroup,
  Page,
  usePagination,
} from "@ajna/pagination";

const Minimal: FC = () => {
  const { currentPage, setCurrentPage, pagesCount } = usePagination({
    pagesCount: 12,
    initialState: { currentPage: 1 },
  });

  return (
    <ChakraProvider>
      <Pagination
        pagesCount={pagesCount}
        currentPage={currentPage}
        onPageChange={handlePageChange}
      >
        <PaginationContainer>
          <PaginationPrevious>Previous</PaginationPrevious>
          <PaginationPageGroup>
            {pages.map((page: number) => (
              <PaginationPage key={`pagination_page_${page}`} page={page} />
            ))}
          </PaginationPageGroup>
          <PaginationNext>Next</PaginationNext>
        </PaginationContainer>
      </Pagination>
    </ChakraProvider>
  );
};

export default Demo;

Styling

The _current prop will contain the props for the page which is currently selected
All other props will apply to every other page
<PaginationPage
  w={7}
  bg="red.300"
  fontSize="sm"
  _hover={{
    bg: "green.300"
  }}
  _current={{
    w: 7,
    bg: "green.300"
    fontSize: "sm"
    _hover: {
      bg: "blue.300"
    },
  }}
>

<PaginationPrevious
  bg="blue.500"
  w="20rem"
  //...any button prop
>
  Previous
</PaginationPrevious>

<PaginationNext
  w={7}
  bg="red.300"
  fontSize="sm"
  //...any button prop
>
  Next
</PaginationNext>

<PaginationContainer
  bg="blue.500"
  w="full"
  //...any flex prop
>
  ...
</PaginationContainer>

<PaginationPageGroup
  bg="blue.500"
  w="full"
  //...any stack prop
>
  ...
</PaginationPageGroup>

Disabling

It's provided a commodity disable prop to disable/enable all your pagination components at once
const { isDisabled, setIsDisabled } = usePagination({
  initialState: { isDisabled: false }
});

const handleDisableClick = () => {
  return setIsDisabled((oldState) => !oldState);
};

<Pagination
  isDisabled={isDisabled}
>

Page size

It's provided a commodity page size setter and getter
const { pageSize, setPageSize } = usePagination({
  initialState: { pageSize: 5 },
});

const handlePageSizeChange = (event: ChangeEvent<HTMLSelectElement>) => {
  const pageSize = Number(event.target.value);

  setPageSize(pageSize);
};

Limits

You can trim the ammount of pages you show by passing both limits at the same time
You need to pass them both, otherwise no limits will be applied
const { pages } = usePagination({
  limits: {
    outer: outerLimit,
    inner: innerLimit,
  },
});

Separator

Additionaly, you can customize the separator component used when limits are defined
<PaginationPageGroup separator={<PaginationSeparator _hover={{ bg: 'purple.500' }} bg='teal.500'>}>
  {pages.map((page: number) => (
    <PaginationPage key={`pagination_page_${page}`} page={page} />
  ))}
</PaginationPageGroup>

Offset

It's possible that the API for the pagination you are consuming works with an offset
One it's calculated and provided for you using the pageSize and currentPage values
This is calculated with the next formula:

[currentPage * pageSize - pageSize]

currentPage === 1 && pageSize === 5 // offset = 0;
currentPage === 2 && pageSize === 5 // offset = 5;
currentPage === 3 && pageSize === 5 // offset = 10;
const { offset, pageSize } = usePagination({
  initialState: { pageSize: 5 },
});

fetchUsingOffset(pageSize, offset).then((data) => {
  // use data
});

Total

Keep in mind that if you know the total amount of items of the requested endpoint, which is not
a strange thing to be returned, you can use that to generate the pages for you
const { pages, pagesCount } = usePaginator({
  total: 4021,
  initialState: { pageSize: 5 }
});

<Pagination
  pagesCount={pagesCount}
>

<PaginationPageGroup>
  {pages.map((page: number) => (
    <PaginationPage key={`pagination_page_${page}`} page={page} />
  ))}
</PaginationPageGroup>

Full usage example

In this example you can see all the possible features provided by the library being applied
to show 10 pokemons names, with the ability to play with the page size and disable state
import React, { FC, ChangeEvent, useEffect, useState } from "react";
import { Grid, Center, Select, Text, Button, Stack } from "@chakra-ui/react";
import {
  Pagination,
  usePagination,
  PaginationPage,
  PaginationNext,
  PaginationPrevious,
  PaginationPageGroup,
  PaginationContainer,
  PaginationSeparator,
} from "@ajna/pagination";

const fetchPokemons = async (
  pageSize: number,
  offset: number
): Promise<any> => {
  return await fetch(
    `https://pokeapi.co/api/v2/pokemon?limit=${pageSize}&offset=${offset}`
  ).then(async (res) => await res.json());
};

const Full: FC = () => {
  // states
  const [pokemonsTotal, setPokemonsTotal] = useState<number | undefined>(
    undefined
  );
  const [pokemons, setPokemons] = useState<any[]>([]);

  // constants
  const outerLimit = 2;
  const innerLimit = 2;

  const {
    pages,
    pagesCount,
    offset,
    currentPage,
    setCurrentPage,
    setIsDisabled,
    isDisabled,
    pageSize,
    setPageSize,
  } = usePagination({
    total: pokemonsTotal,
    limits: {
      outer: outerLimit,
      inner: innerLimit,
    },
    initialState: {
      pageSize: 5,
      isDisabled: false,
      currentPage: 1,
    },
  });
  // effects
  useEffect(() => {
    fetchPokemons(pageSize, offset)
      .then((pokemons) => {
        setPokemonsTotal(pokemons.count);
        setPokemons(pokemons.results);
      })
      .catch((error) => console.error("App =>", error));
  }, [currentPage, pageSize, offset]);

  // handlers
  const handlePageChange = (nextPage: number): void => {
    // -> request new data using the page number
    setCurrentPage(nextPage);
    console.log("request new data with ->", nextPage);
  };

  const handlePageSizeChange = (
    event: ChangeEvent<HTMLSelectElement>
  ): void => {
    const pageSize = Number(event.target.value);

    setPageSize(pageSize);
  };

  const handleDisableClick = (): void => {
    setIsDisabled((oldState) => !oldState);
  };

  return (
    <Stack>
      <Pagination
        pagesCount={pagesCount}
        currentPage={currentPage}
        isDisabled={isDisabled}
        onPageChange={handlePageChange}
      >
        <PaginationContainer
          align="center"
          justify="space-between"
          p={4}
          w="full"
        >
          <PaginationPrevious
            _hover={{
              bg: "yellow.400",
            }}
            bg="yellow.300"
            isDisabled
            onClick={() => console.warn("I'm clicking the previous")}
          >
            <Text>Previous</Text>
          </PaginationPrevious>
          <PaginationPageGroup
            isInline
            align="center"
            separator={
              <PaginationSeparator
                isDisabled
                onClick={() => console.warn("I'm clicking the separator")}
                bg="blue.300"
                fontSize="sm"
                w={7}
                jumpSize={11}
              />
            }
          >
            {pages.map((page: number) => (
              <PaginationPage
                w={7}
                bg="red.300"
                key={`pagination_page_${page}`}
                page={page}
                onClick={() => console.warn("Im clicking the page")}
                fontSize="sm"
                _hover={{
                  bg: "green.300",
                }}
                _current={{
                  bg: "green.300",
                  fontSize: "sm",
                  w: 7,
                }}
              />
            ))}
          </PaginationPageGroup>
          <PaginationNext
            _hover={{
              bg: "yellow.400",
            }}
            bg="yellow.300"
            onClick={() => console.warn("I'm clicking the next")}
          >
            <Text>Next</Text>
          </PaginationNext>
        </PaginationContainer>
      </Pagination>
      <Center w="full">
        <Button
          _hover={{
            bg: "purple.400",
          }}
          bg="purple.300"
          onClick={handleDisableClick}
        >
          Disable ON / OFF
        </Button>
        <Select ml={3} onChange={handlePageSizeChange} w={40}>
          <option value="10">10</option>
          <option value="25">25</option>
          <option value="50">50</option>
        </Select>
      </Center>
      <Grid
        gap={3}
        mt={20}
        px={20}
        templateColumns="repeat(5, 1fr)"
        templateRows="repeat(2, 1fr)"
      >
        {pokemons?.map(({ name }) => (
          <Center key={name} bg="green.100" p={4}>
            <Text>{name}</Text>
          </Center>
        ))}
      </Grid>
    </Stack>
  );
};

export default Full;

Keywords

FAQs

Package last updated on 28 Jul 2021

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc